1 /* $NetBSD: freebsd_file.c,v 1.9 1998/02/19 00:36:03 thorpej 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 "fs_nfs.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/namei.h> 41 #include <sys/proc.h> 42 #include <sys/file.h> 43 #include <sys/stat.h> 44 #include <sys/filedesc.h> 45 #include <sys/ioctl.h> 46 #include <sys/kernel.h> 47 #include <sys/mount.h> 48 #include <sys/malloc.h> 49 50 #include <sys/syscallargs.h> 51 52 #include <compat/freebsd/freebsd_syscallargs.h> 53 #include <compat/freebsd/freebsd_util.h> 54 55 #define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) 56 57 const char freebsd_emul_path[] = "/emul/freebsd"; 58 59 static char * convert_from_freebsd_mount_type __P((int)); 60 61 static char * 62 convert_from_freebsd_mount_type(type) 63 int type; 64 { 65 static char *netbsd_mount_type[] = { 66 NULL, /* 0 = MOUNT_NONE */ 67 "ffs", /* 1 = "Fast" Filesystem */ 68 "nfs", /* 2 = Network Filesystem */ 69 "mfs", /* 3 = Memory Filesystem */ 70 "msdos", /* 4 = MSDOS Filesystem */ 71 "lfs", /* 5 = Log-based Filesystem */ 72 "lofs", /* 6 = Loopback filesystem */ 73 "fdesc", /* 7 = File Descriptor Filesystem */ 74 "portal", /* 8 = Portal Filesystem */ 75 "null", /* 9 = Minimal Filesystem Layer */ 76 "umap", /* 10 = User/Group Identifier Remapping Filesystem */ 77 "kernfs", /* 11 = Kernel Information Filesystem */ 78 "procfs", /* 12 = /proc Filesystem */ 79 "afs", /* 13 = Andrew Filesystem */ 80 "cd9660", /* 14 = ISO9660 (aka CDROM) Filesystem */ 81 "union", /* 15 = Union (translucent) Filesystem */ 82 NULL, /* 16 = "devfs" - existing device Filesystem */ 83 #if 0 /* These filesystems don't exist in FreeBSD */ 84 "adosfs", /* ?? = AmigaDOS Filesystem */ 85 #endif 86 }; 87 88 if (type < 0 || type >= ARRAY_LENGTH(netbsd_mount_type)) 89 return (NULL); 90 return (netbsd_mount_type[type]); 91 } 92 93 int 94 freebsd_sys_mount(p, v, retval) 95 struct proc *p; 96 void *v; 97 register_t *retval; 98 { 99 struct freebsd_sys_mount_args /* { 100 syscallarg(int) type; 101 syscallarg(char *) path; 102 syscallarg(int) flags; 103 syscallarg(caddr_t) data; 104 } */ *uap = v; 105 int error; 106 char *type, *s; 107 caddr_t sg = stackgap_init(p->p_emul); 108 struct sys_mount_args bma; 109 110 if ((type = convert_from_freebsd_mount_type(SCARG(uap, type))) == NULL) 111 return ENODEV; 112 s = stackgap_alloc(&sg, MFSNAMELEN + 1); 113 if ((error = copyout(type, s, strlen(type) + 1)) != 0) 114 return error; 115 SCARG(&bma, type) = s; 116 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 117 SCARG(&bma, path) = SCARG(uap, path); 118 SCARG(&bma, flags) = SCARG(uap, flags); 119 SCARG(&bma, data) = SCARG(uap, data); 120 return sys_mount(p, &bma, retval); 121 } 122 123 /* 124 * The following syscalls are only here because of the alternate path check. 125 */ 126 127 /* XXX - UNIX domain: int freebsd_sys_bind(int s, caddr_t name, int namelen); */ 128 /* XXX - UNIX domain: int freebsd_sys_connect(int s, caddr_t name, int namelen); */ 129 130 131 int 132 freebsd_sys_open(p, v, retval) 133 struct proc *p; 134 void *v; 135 register_t *retval; 136 { 137 struct freebsd_sys_open_args /* { 138 syscallarg(char *) path; 139 syscallarg(int) flags; 140 syscallarg(int) mode; 141 } */ *uap = v; 142 caddr_t sg = stackgap_init(p->p_emul); 143 144 if (SCARG(uap, flags) & O_CREAT) 145 FREEBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 146 else 147 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 148 return sys_open(p, uap, retval); 149 } 150 151 int 152 compat_43_freebsd_sys_creat(p, v, retval) 153 struct proc *p; 154 void *v; 155 register_t *retval; 156 { 157 struct compat_43_freebsd_sys_creat_args /* { 158 syscallarg(char *) path; 159 syscallarg(int) mode; 160 } */ *uap = v; 161 caddr_t sg = stackgap_init(p->p_emul); 162 163 FREEBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 164 return compat_43_sys_creat(p, uap, retval); 165 } 166 167 int 168 freebsd_sys_link(p, v, retval) 169 struct proc *p; 170 void *v; 171 register_t *retval; 172 { 173 struct freebsd_sys_link_args /* { 174 syscallarg(char *) path; 175 syscallarg(char *) link; 176 } */ *uap = v; 177 caddr_t sg = stackgap_init(p->p_emul); 178 179 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 180 FREEBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, link)); 181 return sys_link(p, uap, retval); 182 } 183 184 int 185 freebsd_sys_unlink(p, v, retval) 186 struct proc *p; 187 void *v; 188 register_t *retval; 189 { 190 struct freebsd_sys_unlink_args /* { 191 syscallarg(char *) path; 192 } */ *uap = v; 193 caddr_t sg = stackgap_init(p->p_emul); 194 195 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 196 return sys_unlink(p, uap, retval); 197 } 198 199 int 200 freebsd_sys_chdir(p, v, retval) 201 struct proc *p; 202 void *v; 203 register_t *retval; 204 { 205 struct freebsd_sys_chdir_args /* { 206 syscallarg(char *) path; 207 } */ *uap = v; 208 caddr_t sg = stackgap_init(p->p_emul); 209 210 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 211 return sys_chdir(p, uap, retval); 212 } 213 214 int 215 freebsd_sys_mknod(p, v, retval) 216 struct proc *p; 217 void *v; 218 register_t *retval; 219 { 220 struct freebsd_sys_mknod_args /* { 221 syscallarg(char *) path; 222 syscallarg(int) mode; 223 syscallarg(int) dev; 224 } */ *uap = v; 225 caddr_t sg = stackgap_init(p->p_emul); 226 227 FREEBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 228 return sys_mknod(p, uap, retval); 229 } 230 231 int 232 freebsd_sys_chmod(p, v, retval) 233 struct proc *p; 234 void *v; 235 register_t *retval; 236 { 237 struct freebsd_sys_chmod_args /* { 238 syscallarg(char *) path; 239 syscallarg(int) mode; 240 } */ *uap = v; 241 caddr_t sg = stackgap_init(p->p_emul); 242 243 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 244 return sys_chmod(p, uap, retval); 245 } 246 247 int 248 freebsd_sys_chown(p, v, retval) 249 struct proc *p; 250 void *v; 251 register_t *retval; 252 { 253 struct freebsd_sys_chown_args /* { 254 syscallarg(char *) path; 255 syscallarg(int) uid; 256 syscallarg(int) gid; 257 } */ *uap = v; 258 caddr_t sg = stackgap_init(p->p_emul); 259 260 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 261 return sys_chown(p, uap, retval); 262 } 263 264 int 265 freebsd_sys_lchown(p, v, retval) 266 struct proc *p; 267 void *v; 268 register_t *retval; 269 { 270 struct freebsd_sys_lchown_args /* { 271 syscallarg(char *) path; 272 syscallarg(int) uid; 273 syscallarg(int) gid; 274 } */ *uap = v; 275 caddr_t sg = stackgap_init(p->p_emul); 276 277 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 278 return sys_lchown(p, uap, retval); 279 } 280 281 int 282 freebsd_sys_unmount(p, v, retval) 283 struct proc *p; 284 void *v; 285 register_t *retval; 286 { 287 struct freebsd_sys_unmount_args /* { 288 syscallarg(char *) path; 289 syscallarg(int) flags; 290 } */ *uap = v; 291 caddr_t sg = stackgap_init(p->p_emul); 292 293 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 294 return sys_unmount(p, uap, retval); 295 } 296 297 int 298 freebsd_sys_access(p, v, retval) 299 struct proc *p; 300 void *v; 301 register_t *retval; 302 { 303 struct freebsd_sys_access_args /* { 304 syscallarg(char *) path; 305 syscallarg(int) flags; 306 } */ *uap = v; 307 caddr_t sg = stackgap_init(p->p_emul); 308 309 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 310 return sys_access(p, uap, retval); 311 } 312 313 int 314 freebsd_sys_chflags(p, v, retval) 315 struct proc *p; 316 void *v; 317 register_t *retval; 318 { 319 struct freebsd_sys_chflags_args /* { 320 syscallarg(char *) path; 321 syscallarg(int) flags; 322 } */ *uap = v; 323 caddr_t sg = stackgap_init(p->p_emul); 324 325 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 326 return sys_chflags(p, uap, retval); 327 } 328 329 int 330 compat_43_freebsd_sys_stat(p, v, retval) 331 struct proc *p; 332 void *v; 333 register_t *retval; 334 { 335 struct compat_43_freebsd_sys_stat_args /* { 336 syscallarg(char *) path; 337 syscallarg(struct stat43 *) ub; 338 } */ *uap = v; 339 caddr_t sg = stackgap_init(p->p_emul); 340 341 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 342 return compat_43_sys_stat(p, uap, retval); 343 } 344 345 int 346 compat_43_freebsd_sys_lstat(p, v, retval) 347 struct proc *p; 348 void *v; 349 register_t *retval; 350 { 351 struct compat_43_freebsd_sys_lstat_args /* { 352 syscallarg(char *) path; 353 syscallarg(struct stat43 *) ub; 354 } */ *uap = v; 355 caddr_t sg = stackgap_init(p->p_emul); 356 357 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 358 return compat_43_sys_lstat(p, uap, retval); 359 } 360 361 int 362 freebsd_sys_revoke(p, v, retval) 363 struct proc *p; 364 void *v; 365 register_t *retval; 366 { 367 struct freebsd_sys_revoke_args /* { 368 syscallarg(char *) path; 369 } */ *uap = v; 370 caddr_t sg = stackgap_init(p->p_emul); 371 372 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 373 return sys_revoke(p, uap, retval); 374 } 375 376 int 377 freebsd_sys_symlink(p, v, retval) 378 struct proc *p; 379 void *v; 380 register_t *retval; 381 { 382 struct freebsd_sys_symlink_args /* { 383 syscallarg(char *) path; 384 syscallarg(char *) link; 385 } */ *uap = v; 386 caddr_t sg = stackgap_init(p->p_emul); 387 388 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 389 FREEBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, link)); 390 return sys_symlink(p, uap, retval); 391 } 392 393 int 394 freebsd_sys_readlink(p, v, retval) 395 struct proc *p; 396 void *v; 397 register_t *retval; 398 { 399 struct freebsd_sys_readlink_args /* { 400 syscallarg(char *) path; 401 syscallarg(char *) buf; 402 syscallarg(int) count; 403 } */ *uap = v; 404 caddr_t sg = stackgap_init(p->p_emul); 405 406 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 407 return sys_readlink(p, uap, retval); 408 } 409 410 int 411 freebsd_sys_execve(p, v, retval) 412 struct proc *p; 413 void *v; 414 register_t *retval; 415 { 416 struct freebsd_sys_execve_args /* { 417 syscallarg(char *) path; 418 syscallarg(char **) argp; 419 syscallarg(char **) envp; 420 } */ *uap = v; 421 struct sys_execve_args ap; 422 caddr_t sg; 423 424 sg = stackgap_init(p->p_emul); 425 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 426 427 SCARG(&ap, path) = SCARG(uap, path); 428 SCARG(&ap, argp) = SCARG(uap, argp); 429 SCARG(&ap, envp) = SCARG(uap, envp); 430 431 return sys_execve(p, &ap, retval); 432 } 433 434 int 435 freebsd_sys_chroot(p, v, retval) 436 struct proc *p; 437 void *v; 438 register_t *retval; 439 { 440 struct freebsd_sys_chroot_args /* { 441 syscallarg(char *) path; 442 } */ *uap = v; 443 caddr_t sg = stackgap_init(p->p_emul); 444 445 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 446 return sys_chroot(p, uap, retval); 447 } 448 449 int 450 freebsd_sys_rename(p, v, retval) 451 struct proc *p; 452 void *v; 453 register_t *retval; 454 { 455 struct freebsd_sys_rename_args /* { 456 syscallarg(char *) from; 457 syscallarg(char *) to; 458 } */ *uap = v; 459 caddr_t sg = stackgap_init(p->p_emul); 460 461 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from)); 462 FREEBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 463 return sys_rename(p, uap, retval); 464 } 465 466 int 467 compat_43_freebsd_sys_truncate(p, v, retval) 468 struct proc *p; 469 void *v; 470 register_t *retval; 471 { 472 struct compat_43_freebsd_sys_truncate_args /* { 473 syscallarg(char *) path; 474 syscallarg(long) length; 475 } */ *uap = v; 476 caddr_t sg = stackgap_init(p->p_emul); 477 478 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 479 return compat_43_sys_truncate(p, uap, retval); 480 } 481 482 int 483 freebsd_sys_mkfifo(p, v, retval) 484 struct proc *p; 485 void *v; 486 register_t *retval; 487 { 488 struct freebsd_sys_mkfifo_args /* { 489 syscallarg(char *) path; 490 syscallarg(int) mode; 491 } */ *uap = v; 492 caddr_t sg = stackgap_init(p->p_emul); 493 494 FREEBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 495 return sys_mkfifo(p, uap, retval); 496 } 497 498 int 499 freebsd_sys_mkdir(p, v, retval) 500 struct proc *p; 501 void *v; 502 register_t *retval; 503 { 504 struct freebsd_sys_mkdir_args /* { 505 syscallarg(char *) path; 506 syscallarg(int) mode; 507 } */ *uap = v; 508 caddr_t sg = stackgap_init(p->p_emul); 509 510 FREEBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 511 return sys_mkdir(p, uap, retval); 512 } 513 514 int 515 freebsd_sys_rmdir(p, v, retval) 516 struct proc *p; 517 void *v; 518 register_t *retval; 519 { 520 struct freebsd_sys_rmdir_args /* { 521 syscallarg(char *) path; 522 } */ *uap = v; 523 caddr_t sg = stackgap_init(p->p_emul); 524 525 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 526 return sys_rmdir(p, uap, retval); 527 } 528 529 int 530 freebsd_sys_statfs(p, v, retval) 531 struct proc *p; 532 void *v; 533 register_t *retval; 534 { 535 struct freebsd_sys_stat_args /* { 536 syscallarg(char *) path; 537 syscallarg(struct statfs *) buf; 538 } */ *uap = v; 539 caddr_t sg = stackgap_init(p->p_emul); 540 541 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 542 return sys_statfs(p, uap, retval); 543 } 544 545 #ifdef NFS 546 int 547 freebsd_sys_getfh(p, v, retval) 548 struct proc *p; 549 void *v; 550 register_t *retval; 551 { 552 struct freebsd_sys_getfh_args /* { 553 syscallarg(char *) fname; 554 syscallarg(fhandle_t *) fhp; 555 } */ *uap = v; 556 caddr_t sg = stackgap_init(p->p_emul); 557 558 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, fname)); 559 return sys_getfh(p, uap, retval); 560 } 561 #endif /* NFS */ 562 563 int 564 freebsd_sys_stat(p, v, retval) 565 struct proc *p; 566 void *v; 567 register_t *retval; 568 { 569 struct freebsd_sys_stat_args /* { 570 syscallarg(char *) path; 571 syscallarg(struct stat12 *) ub; 572 } */ *uap = v; 573 caddr_t sg = stackgap_init(p->p_emul); 574 575 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 576 return compat_12_sys_stat(p, uap, retval); 577 } 578 579 int 580 freebsd_sys_lstat(p, v, retval) 581 struct proc *p; 582 void *v; 583 register_t *retval; 584 { 585 struct freebsd_sys_lstat_args /* { 586 syscallarg(char *) path; 587 syscallarg(struct stat12 *) ub; 588 } */ *uap = v; 589 caddr_t sg = stackgap_init(p->p_emul); 590 591 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 592 return compat_12_sys_lstat(p, uap, retval); 593 } 594 595 int 596 freebsd_sys_pathconf(p, v, retval) 597 struct proc *p; 598 void *v; 599 register_t *retval; 600 { 601 struct freebsd_sys_pathconf_args /* { 602 syscallarg(char *) path; 603 syscallarg(int) name; 604 } */ *uap = v; 605 caddr_t sg = stackgap_init(p->p_emul); 606 607 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 608 return sys_pathconf(p, uap, retval); 609 } 610 611 int 612 freebsd_sys_truncate(p, v, retval) 613 struct proc *p; 614 void *v; 615 register_t *retval; 616 { 617 struct freebsd_sys_truncate_args /* { 618 syscallarg(char *) path; 619 syscallarg(int) pad; 620 syscallarg(off_t) length; 621 } */ *uap = v; 622 caddr_t sg = stackgap_init(p->p_emul); 623 624 FREEBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 625 return sys_truncate(p, uap, retval); 626 } 627