freebsd_file.c revision 1.20
1/* $NetBSD: freebsd_file.c,v 1.20 2004/04/21 01:05:36 christos Exp $ */ 2 3/* 4 * Copyright (c) 1995 Frank van der Linden 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project 18 * by Frank van der Linden 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * from: linux_file.c,v 1.3 1995/04/04 04:21:30 mycroft Exp 34 */ 35 36#include <sys/cdefs.h> 37__KERNEL_RCSID(0, "$NetBSD: freebsd_file.c,v 1.20 2004/04/21 01:05:36 christos Exp $"); 38 39#if defined(_KERNEL_OPT) 40#include "fs_nfs.h" 41#endif 42 43#include <sys/param.h> 44#include <sys/systm.h> 45#include <sys/namei.h> 46#include <sys/proc.h> 47#include <sys/file.h> 48#include <sys/stat.h> 49#include <sys/filedesc.h> 50#include <sys/ioctl.h> 51#include <sys/kernel.h> 52#include <sys/mount.h> 53#include <sys/malloc.h> 54 55#include <sys/sa.h> 56#include <sys/syscallargs.h> 57 58#include <compat/freebsd/freebsd_syscallargs.h> 59#include <compat/common/compat_util.h> 60 61#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) 62 63static const char * convert_from_freebsd_mount_type __P((int)); 64 65static const char * 66convert_from_freebsd_mount_type(type) 67 int type; 68{ 69 static const char * const netbsd_mount_type[] = { 70 NULL, /* 0 = MOUNT_NONE */ 71 "ffs", /* 1 = "Fast" Filesystem */ 72 "nfs", /* 2 = Network Filesystem */ 73 "mfs", /* 3 = Memory Filesystem */ 74 "msdos", /* 4 = MSDOS Filesystem */ 75 "lfs", /* 5 = Log-based Filesystem */ 76 "lofs", /* 6 = Loopback filesystem */ 77 "fdesc", /* 7 = File Descriptor Filesystem */ 78 "portal", /* 8 = Portal Filesystem */ 79 "null", /* 9 = Minimal Filesystem Layer */ 80 "umap", /* 10 = User/Group Identifier Remapping Filesystem */ 81 "kernfs", /* 11 = Kernel Information Filesystem */ 82 "procfs", /* 12 = /proc Filesystem */ 83 "afs", /* 13 = Andrew Filesystem */ 84 "cd9660", /* 14 = ISO9660 (aka CDROM) Filesystem */ 85 "union", /* 15 = Union (translucent) Filesystem */ 86 NULL, /* 16 = "devfs" - existing device Filesystem */ 87#if 0 /* These filesystems don't exist in FreeBSD */ 88 "adosfs", /* ?? = AmigaDOS Filesystem */ 89#endif 90 }; 91 92 if (type < 0 || type >= ARRAY_LENGTH(netbsd_mount_type)) 93 return (NULL); 94 return (netbsd_mount_type[type]); 95} 96 97int 98freebsd_sys_mount(l, v, retval) 99 struct lwp *l; 100 void *v; 101 register_t *retval; 102{ 103 struct freebsd_sys_mount_args /* { 104 syscallarg(int) type; 105 syscallarg(char *) path; 106 syscallarg(int) flags; 107 syscallarg(caddr_t) data; 108 } */ *uap = v; 109 struct proc *p = l->l_proc; 110 int error; 111 const char *type; 112 char *s; 113 caddr_t sg = stackgap_init(p, 0); 114 struct sys_mount_args bma; 115 116 if ((type = convert_from_freebsd_mount_type(SCARG(uap, type))) == NULL) 117 return ENODEV; 118 s = stackgap_alloc(p, &sg, MFSNAMELEN + 1); 119 if ((error = copyout(type, s, strlen(type) + 1)) != 0) 120 return error; 121 SCARG(&bma, type) = s; 122 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 123 SCARG(&bma, path) = SCARG(uap, path); 124 SCARG(&bma, flags) = SCARG(uap, flags); 125 SCARG(&bma, data) = SCARG(uap, data); 126 return sys_mount(l, &bma, retval); 127} 128 129/* 130 * The following syscalls are only here because of the alternate path check. 131 */ 132 133/* XXX - UNIX domain: int freebsd_sys_bind(int s, caddr_t name, int namelen); */ 134/* XXX - UNIX domain: int freebsd_sys_connect(int s, caddr_t name, int namelen); */ 135 136 137int 138freebsd_sys_open(l, v, retval) 139 struct lwp *l; 140 void *v; 141 register_t *retval; 142{ 143 struct freebsd_sys_open_args /* { 144 syscallarg(char *) path; 145 syscallarg(int) flags; 146 syscallarg(int) mode; 147 } */ *uap = v; 148 struct proc *p = l->l_proc; 149 caddr_t sg = stackgap_init(p, 0); 150 151 if (SCARG(uap, flags) & O_CREAT) 152 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 153 else 154 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 155 return sys_open(l, uap, retval); 156} 157 158int 159compat_43_freebsd_sys_creat(l, v, retval) 160 struct lwp *l; 161 void *v; 162 register_t *retval; 163{ 164 struct compat_43_freebsd_sys_creat_args /* { 165 syscallarg(char *) path; 166 syscallarg(int) mode; 167 } */ *uap = v; 168 struct proc *p = l->l_proc; 169 caddr_t sg = stackgap_init(p, 0); 170 171 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 172 return compat_43_sys_creat(l, uap, retval); 173} 174 175int 176freebsd_sys_link(l, v, retval) 177 struct lwp *l; 178 void *v; 179 register_t *retval; 180{ 181 struct freebsd_sys_link_args /* { 182 syscallarg(char *) path; 183 syscallarg(char *) link; 184 } */ *uap = v; 185 struct proc *p = l->l_proc; 186 caddr_t sg = stackgap_init(p, 0); 187 188 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 189 CHECK_ALT_CREAT(p, &sg, SCARG(uap, link)); 190 return sys_link(l, uap, retval); 191} 192 193int 194freebsd_sys_unlink(l, v, retval) 195 struct lwp *l; 196 void *v; 197 register_t *retval; 198{ 199 struct freebsd_sys_unlink_args /* { 200 syscallarg(char *) path; 201 } */ *uap = v; 202 struct proc *p = l->l_proc; 203 caddr_t sg = stackgap_init(p, 0); 204 205 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 206 return sys_unlink(l, uap, retval); 207} 208 209int 210freebsd_sys_chdir(l, v, retval) 211 struct lwp *l; 212 void *v; 213 register_t *retval; 214{ 215 struct freebsd_sys_chdir_args /* { 216 syscallarg(char *) path; 217 } */ *uap = v; 218 struct proc *p = l->l_proc; 219 caddr_t sg = stackgap_init(p, 0); 220 221 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 222 return sys_chdir(l, uap, retval); 223} 224 225int 226freebsd_sys_mknod(l, v, retval) 227 struct lwp *l; 228 void *v; 229 register_t *retval; 230{ 231 struct freebsd_sys_mknod_args /* { 232 syscallarg(char *) path; 233 syscallarg(int) mode; 234 syscallarg(int) dev; 235 } */ *uap = v; 236 struct proc *p = l->l_proc; 237 caddr_t sg = stackgap_init(p, 0); 238 239 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 240 return sys_mknod(l, uap, retval); 241} 242 243int 244freebsd_sys_chmod(l, v, retval) 245 struct lwp *l; 246 void *v; 247 register_t *retval; 248{ 249 struct freebsd_sys_chmod_args /* { 250 syscallarg(char *) path; 251 syscallarg(int) mode; 252 } */ *uap = v; 253 struct proc *p = l->l_proc; 254 caddr_t sg = stackgap_init(p, 0); 255 256 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 257 return sys_chmod(l, uap, retval); 258} 259 260int 261freebsd_sys_chown(l, v, retval) 262 struct lwp *l; 263 void *v; 264 register_t *retval; 265{ 266 struct freebsd_sys_chown_args /* { 267 syscallarg(char *) path; 268 syscallarg(int) uid; 269 syscallarg(int) gid; 270 } */ *uap = v; 271 struct proc *p = l->l_proc; 272 caddr_t sg = stackgap_init(p, 0); 273 274 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 275 return sys_chown(l, uap, retval); 276} 277 278int 279freebsd_sys_lchown(l, v, retval) 280 struct lwp *l; 281 void *v; 282 register_t *retval; 283{ 284 struct freebsd_sys_lchown_args /* { 285 syscallarg(char *) path; 286 syscallarg(int) uid; 287 syscallarg(int) gid; 288 } */ *uap = v; 289 struct proc *p = l->l_proc; 290 caddr_t sg = stackgap_init(p, 0); 291 292 CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path)); 293 return sys_lchown(l, uap, retval); 294} 295 296int 297freebsd_sys_unmount(l, v, retval) 298 struct lwp *l; 299 void *v; 300 register_t *retval; 301{ 302 struct freebsd_sys_unmount_args /* { 303 syscallarg(char *) path; 304 syscallarg(int) flags; 305 } */ *uap = v; 306 struct proc *p = l->l_proc; 307 caddr_t sg = stackgap_init(p, 0); 308 309 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 310 return sys_unmount(l, uap, retval); 311} 312 313int 314freebsd_sys_access(l, v, retval) 315 struct lwp *l; 316 void *v; 317 register_t *retval; 318{ 319 struct freebsd_sys_access_args /* { 320 syscallarg(char *) path; 321 syscallarg(int) flags; 322 } */ *uap = v; 323 struct proc *p = l->l_proc; 324 caddr_t sg = stackgap_init(p, 0); 325 326 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 327 return sys_access(l, uap, retval); 328} 329 330int 331freebsd_sys_chflags(l, v, retval) 332 struct lwp *l; 333 void *v; 334 register_t *retval; 335{ 336 struct freebsd_sys_chflags_args /* { 337 syscallarg(char *) path; 338 syscallarg(int) flags; 339 } */ *uap = v; 340 struct proc *p = l->l_proc; 341 caddr_t sg = stackgap_init(p, 0); 342 343 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 344 return sys_chflags(l, uap, retval); 345} 346 347int 348compat_43_freebsd_sys_stat(l, v, retval) 349 struct lwp *l; 350 void *v; 351 register_t *retval; 352{ 353 struct compat_43_freebsd_sys_stat_args /* { 354 syscallarg(char *) path; 355 syscallarg(struct stat43 *) ub; 356 } */ *uap = v; 357 struct proc *p = l->l_proc; 358 caddr_t sg = stackgap_init(p, 0); 359 360 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 361 return compat_43_sys_stat(l, uap, retval); 362} 363 364int 365compat_43_freebsd_sys_lstat(l, v, retval) 366 struct lwp *l; 367 void *v; 368 register_t *retval; 369{ 370 struct compat_43_freebsd_sys_lstat_args /* { 371 syscallarg(char *) path; 372 syscallarg(struct stat43 *) ub; 373 } */ *uap = v; 374 struct proc *p = l->l_proc; 375 caddr_t sg = stackgap_init(p, 0); 376 377 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 378 return compat_43_sys_lstat(l, uap, retval); 379} 380 381int 382freebsd_sys_revoke(l, v, retval) 383 struct lwp *l; 384 void *v; 385 register_t *retval; 386{ 387 struct freebsd_sys_revoke_args /* { 388 syscallarg(char *) path; 389 } */ *uap = v; 390 struct proc *p = l->l_proc; 391 caddr_t sg = stackgap_init(p, 0); 392 393 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 394 return sys_revoke(l, uap, retval); 395} 396 397int 398freebsd_sys_symlink(l, v, retval) 399 struct lwp *l; 400 void *v; 401 register_t *retval; 402{ 403 struct freebsd_sys_symlink_args /* { 404 syscallarg(char *) path; 405 syscallarg(char *) link; 406 } */ *uap = v; 407 struct proc *p = l->l_proc; 408 caddr_t sg = stackgap_init(p, 0); 409 410 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 411 CHECK_ALT_CREAT(p, &sg, SCARG(uap, link)); 412 return sys_symlink(l, uap, retval); 413} 414 415int 416freebsd_sys_readlink(l, v, retval) 417 struct lwp *l; 418 void *v; 419 register_t *retval; 420{ 421 struct freebsd_sys_readlink_args /* { 422 syscallarg(char *) path; 423 syscallarg(char *) buf; 424 syscallarg(int) count; 425 } */ *uap = v; 426 struct proc *p = l->l_proc; 427 caddr_t sg = stackgap_init(p, 0); 428 429 CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path)); 430 return sys_readlink(l, uap, retval); 431} 432 433int 434freebsd_sys_execve(l, v, retval) 435 struct lwp *l; 436 void *v; 437 register_t *retval; 438{ 439 struct freebsd_sys_execve_args /* { 440 syscallarg(char *) path; 441 syscallarg(char **) argp; 442 syscallarg(char **) envp; 443 } */ *uap = v; 444 struct proc *p = l->l_proc; 445 struct sys_execve_args ap; 446 caddr_t sg; 447 448 sg = stackgap_init(p, 0); 449 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 450 451 SCARG(&ap, path) = SCARG(uap, path); 452 SCARG(&ap, argp) = SCARG(uap, argp); 453 SCARG(&ap, envp) = SCARG(uap, envp); 454 455 return sys_execve(l, &ap, retval); 456} 457 458int 459freebsd_sys_chroot(l, v, retval) 460 struct lwp *l; 461 void *v; 462 register_t *retval; 463{ 464 struct freebsd_sys_chroot_args /* { 465 syscallarg(char *) path; 466 } */ *uap = v; 467 struct proc *p = l->l_proc; 468 caddr_t sg = stackgap_init(p, 0); 469 470 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 471 return sys_chroot(l, uap, retval); 472} 473 474int 475freebsd_sys_rename(l, v, retval) 476 struct lwp *l; 477 void *v; 478 register_t *retval; 479{ 480 struct freebsd_sys_rename_args /* { 481 syscallarg(char *) from; 482 syscallarg(char *) to; 483 } */ *uap = v; 484 struct proc *p = l->l_proc; 485 caddr_t sg = stackgap_init(p, 0); 486 487 CHECK_ALT_EXIST(p, &sg, SCARG(uap, from)); 488 CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 489 return sys_rename(l, uap, retval); 490} 491 492int 493compat_43_freebsd_sys_truncate(l, v, retval) 494 struct lwp *l; 495 void *v; 496 register_t *retval; 497{ 498 struct compat_43_freebsd_sys_truncate_args /* { 499 syscallarg(char *) path; 500 syscallarg(long) length; 501 } */ *uap = v; 502 struct proc *p = l->l_proc; 503 caddr_t sg = stackgap_init(p, 0); 504 505 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 506 return compat_43_sys_truncate(l, uap, retval); 507} 508 509int 510freebsd_sys_mkfifo(l, v, retval) 511 struct lwp *l; 512 void *v; 513 register_t *retval; 514{ 515 struct freebsd_sys_mkfifo_args /* { 516 syscallarg(char *) path; 517 syscallarg(int) mode; 518 } */ *uap = v; 519 struct proc *p = l->l_proc; 520 caddr_t sg = stackgap_init(p, 0); 521 522 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 523 return sys_mkfifo(l, uap, retval); 524} 525 526int 527freebsd_sys_mkdir(l, v, retval) 528 struct lwp *l; 529 void *v; 530 register_t *retval; 531{ 532 struct freebsd_sys_mkdir_args /* { 533 syscallarg(char *) path; 534 syscallarg(int) mode; 535 } */ *uap = v; 536 struct proc *p = l->l_proc; 537 caddr_t sg = stackgap_init(p, 0); 538 539 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 540 return sys_mkdir(l, uap, retval); 541} 542 543int 544freebsd_sys_rmdir(l, v, retval) 545 struct lwp *l; 546 void *v; 547 register_t *retval; 548{ 549 struct freebsd_sys_rmdir_args /* { 550 syscallarg(char *) path; 551 } */ *uap = v; 552 struct proc *p = l->l_proc; 553 caddr_t sg = stackgap_init(p, 0); 554 555 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 556 return sys_rmdir(l, uap, retval); 557} 558 559int 560freebsd_sys_statfs(l, v, retval) 561 struct lwp *l; 562 void *v; 563 register_t *retval; 564{ 565 struct freebsd_sys_stat_args /* { 566 syscallarg(char *) path; 567 syscallarg(struct statfs12 *) buf; 568 } */ *uap = v; 569 struct proc *p = l->l_proc; 570 caddr_t sg = stackgap_init(p, 0); 571 572 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 573 return compat_20_sys_statfs(l, uap, retval); 574} 575 576#ifdef NFS 577int 578freebsd_sys_getfh(l, v, retval) 579 struct lwp *l; 580 void *v; 581 register_t *retval; 582{ 583 struct freebsd_sys_getfh_args /* { 584 syscallarg(char *) fname; 585 syscallarg(fhandle_t *) fhp; 586 } */ *uap = v; 587 struct proc *p = l->l_proc; 588 caddr_t sg = stackgap_init(p, 0); 589 590 CHECK_ALT_EXIST(p, &sg, SCARG(uap, fname)); 591 return sys_getfh(l, uap, retval); 592} 593#endif /* NFS */ 594 595int 596freebsd_sys_stat(l, v, retval) 597 struct lwp *l; 598 void *v; 599 register_t *retval; 600{ 601 struct freebsd_sys_stat_args /* { 602 syscallarg(char *) path; 603 syscallarg(struct stat12 *) ub; 604 } */ *uap = v; 605 struct proc *p = l->l_proc; 606 caddr_t sg = stackgap_init(p, 0); 607 608 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 609 return compat_12_sys_stat(l, uap, retval); 610} 611 612int 613freebsd_sys_lstat(l, v, retval) 614 struct lwp *l; 615 void *v; 616 register_t *retval; 617{ 618 struct freebsd_sys_lstat_args /* { 619 syscallarg(char *) path; 620 syscallarg(struct stat12 *) ub; 621 } */ *uap = v; 622 struct proc *p = l->l_proc; 623 caddr_t sg = stackgap_init(p, 0); 624 625 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 626 return compat_12_sys_lstat(l, uap, retval); 627} 628 629int 630freebsd_sys_pathconf(l, v, retval) 631 struct lwp *l; 632 void *v; 633 register_t *retval; 634{ 635 struct freebsd_sys_pathconf_args /* { 636 syscallarg(char *) path; 637 syscallarg(int) name; 638 } */ *uap = v; 639 struct proc *p = l->l_proc; 640 caddr_t sg = stackgap_init(p, 0); 641 642 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 643 return sys_pathconf(l, uap, retval); 644} 645 646int 647freebsd_sys_truncate(l, v, retval) 648 struct lwp *l; 649 void *v; 650 register_t *retval; 651{ 652 struct freebsd_sys_truncate_args /* { 653 syscallarg(char *) path; 654 syscallarg(int) pad; 655 syscallarg(off_t) length; 656 } */ *uap = v; 657 struct proc *p = l->l_proc; 658 caddr_t sg = stackgap_init(p, 0); 659 660 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 661 return sys_truncate(l, uap, retval); 662} 663