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