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