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