2 * Copyright (c) 1994-1995 Søren Schmidt
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software withough specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * $FreeBSD: src/sys/compat/linux/linux_file.c,v 1.41.2.6 2003/01/06 09:19:43 fjoe Exp $
29 * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.39 2008/09/28 05:08:16 dillon Exp $
32 #include "opt_compat.h"
34 #include <sys/param.h>
35 #include <sys/systm.h>
37 #include <sys/dirent.h>
38 #include <sys/fcntl.h>
41 #include <sys/filedesc.h>
42 #include <sys/kern_syscall.h>
44 #include <sys/malloc.h>
45 #include <sys/mount.h>
46 #include <sys/nlookup.h>
48 #include <sys/sysproto.h>
50 #include <sys/vnode.h>
52 #include <vfs/ufs/quota.h>
53 #include <vfs/ufs/ufsmount.h>
55 #include <sys/file2.h>
56 #include <sys/mplock2.h>
58 #include <arch_linux/linux.h>
59 #include <arch_linux/linux_proto.h>
60 #include "linux_util.h"
66 sys_linux_creat(struct linux_creat_args
*args
)
68 struct nlookupdata nd
;
72 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_CREATE
);
77 kprintf(ARGS(creat
, "%s, %d"), path
, args
->mode
);
80 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
82 error
= kern_open(&nd
, O_WRONLY
| O_CREAT
| O_TRUNC
,
83 args
->mode
, &args
->sysmsg_iresult
);
86 linux_free_path(&path
);
94 sys_linux_open(struct linux_open_args
*args
)
96 struct thread
*td
= curthread
;
97 struct proc
*p
= td
->td_proc
;
98 struct nlookupdata nd
;
102 if (args
->flags
& LINUX_O_CREAT
) {
103 error
= linux_copyin_path(args
->path
, &path
,
106 error
= linux_copyin_path(args
->path
, &path
,
114 kprintf(ARGS(open
, "%s, 0x%x, 0x%x"), path
, args
->flags
,
118 if (args
->flags
& LINUX_O_RDONLY
)
120 if (args
->flags
& LINUX_O_WRONLY
)
122 if (args
->flags
& LINUX_O_RDWR
)
124 if (args
->flags
& LINUX_O_NDELAY
)
126 if (args
->flags
& LINUX_O_APPEND
)
128 if (args
->flags
& LINUX_O_SYNC
)
130 if (args
->flags
& LINUX_O_NONBLOCK
)
132 if (args
->flags
& LINUX_FASYNC
)
134 if (args
->flags
& LINUX_O_CREAT
)
136 if (args
->flags
& LINUX_O_TRUNC
)
138 if (args
->flags
& LINUX_O_EXCL
)
140 if (args
->flags
& LINUX_O_NOCTTY
)
143 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
145 error
= kern_open(&nd
, flags
,
146 args
->mode
, &args
->sysmsg_iresult
);
150 if (error
== 0 && !(flags
& O_NOCTTY
) &&
151 SESS_LEADER(p
) && !(p
->p_flag
& P_CONTROLT
)) {
154 fp
= holdfp(p
->p_fd
, args
->sysmsg_iresult
, -1);
156 if (fp
->f_type
== DTYPE_VNODE
) {
157 fo_ioctl(fp
, TIOCSCTTY
, NULL
,
166 kprintf(LMSG("open returns error %d"), error
);
168 linux_free_path(&path
);
173 sys_linux_openat(struct linux_openat_args
*args
)
175 struct thread
*td
= curthread
;
176 struct proc
*p
= td
->td_proc
;
177 struct nlookupdata nd
;
180 int error
, flags
, dfd
;
182 if (args
->flags
& LINUX_O_CREAT
) {
183 error
= linux_copyin_path(args
->path
, &path
,
186 error
= linux_copyin_path(args
->path
, &path
,
194 kprintf(ARGS(open
, "%s, 0x%x, 0x%x"), path
, args
->flags
,
198 if (args
->flags
& LINUX_O_RDONLY
)
200 if (args
->flags
& LINUX_O_WRONLY
)
202 if (args
->flags
& LINUX_O_RDWR
)
204 if (args
->flags
& LINUX_O_NDELAY
)
206 if (args
->flags
& LINUX_O_APPEND
)
208 if (args
->flags
& LINUX_O_SYNC
)
210 if (args
->flags
& LINUX_O_NONBLOCK
)
212 if (args
->flags
& LINUX_FASYNC
)
214 if (args
->flags
& LINUX_O_CREAT
)
216 if (args
->flags
& LINUX_O_TRUNC
)
218 if (args
->flags
& LINUX_O_EXCL
)
220 if (args
->flags
& LINUX_O_NOCTTY
)
223 dfd
= (args
->dfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->dfd
;
225 error
= nlookup_init_at(&nd
, &fp
, dfd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
227 error
= kern_open(&nd
, flags
,
228 args
->mode
, &args
->sysmsg_iresult
);
230 nlookup_done_at(&nd
, fp
);
232 if (error
== 0 && !(flags
& O_NOCTTY
) &&
233 SESS_LEADER(p
) && !(p
->p_flag
& P_CONTROLT
)) {
236 fp
= holdfp(p
->p_fd
, args
->sysmsg_iresult
, -1);
238 if (fp
->f_type
== DTYPE_VNODE
) {
239 fo_ioctl(fp
, TIOCSCTTY
, NULL
,
248 kprintf(LMSG("open returns error %d"), error
);
250 linux_free_path(&path
);
258 sys_linux_lseek(struct linux_lseek_args
*args
)
264 kprintf(ARGS(lseek
, "%d, %ld, %d"),
265 args
->fdes
, (long)args
->off
, args
->whence
);
267 error
= kern_lseek(args
->fdes
, args
->off
, args
->whence
,
268 &args
->sysmsg_offset
);
277 sys_linux_llseek(struct linux_llseek_args
*args
)
284 kprintf(ARGS(llseek
, "%d, %d:%d, %d"),
285 args
->fd
, args
->ohigh
, args
->olow
, args
->whence
);
287 off
= (args
->olow
) | (((off_t
) args
->ohigh
) << 32);
289 error
= kern_lseek(args
->fd
, off
, args
->whence
, &res
);
292 error
= copyout(&res
, args
->res
, sizeof(res
));
300 sys_linux_readdir(struct linux_readdir_args
*args
)
302 struct linux_getdents_args lda
;
306 lda
.dent
= args
->dent
;
308 lda
.sysmsg_iresult
= 0;
309 error
= sys_linux_getdents(&lda
);
310 args
->sysmsg_iresult
= lda
.sysmsg_iresult
;
315 * Note that linux_getdents(2) and linux_getdents64(2) have the same
316 * arguments. They only differ in the definition of struct dirent they
317 * operate on. We use this to common the code, with the exception of
318 * accessing struct dirent. Note that linux_readdir(2) is implemented
319 * by means of linux_getdents(2). In this case we never operate on
320 * struct dirent64 and thus don't need to handle it...
327 char d_name
[LINUX_NAME_MAX
+ 1];
335 char d_name
[LINUX_NAME_MAX
+ 1];
338 #define LINUX_RECLEN(de,namlen) \
339 ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
341 #define LINUX_DIRBLKSIZ 512
347 getdents_common(struct linux_getdents64_args
*args
, int is64bit
)
349 struct thread
*td
= curthread
;
350 struct proc
*p
= td
->td_proc
;
353 caddr_t inp
, buf
; /* BSD-format */
354 int reclen
; /* BSD-format */
356 caddr_t outp
; /* Linux-format */
357 int linuxreclen
= 0; /* Linux-format */
364 struct l_dirent linux_dirent
;
365 struct l_dirent64 linux_dirent64
;
366 int error
, eofflag
, justone
;
367 size_t buflen
, nbytes
;
368 off_t
*cookies
= NULL
, *cookiep
;
371 if ((error
= holdvnode(p
->p_fd
, args
->fd
, &fp
)) != 0)
375 if ((fp
->f_flag
& FREAD
) == 0) {
380 vp
= (struct vnode
*) fp
->f_data
;
381 if (vp
->v_type
!= VDIR
) {
386 if ((error
= VOP_GETATTR(vp
, &va
)) != 0)
389 nbytes
= args
->count
;
390 if (nbytes
== (size_t)-1) {
391 /* readdir(2) case. Always struct dirent. */
396 nbytes
= sizeof(linux_dirent
);
401 if ((size_t)nbytes
< 0)
406 buflen
= max(LINUX_DIRBLKSIZ
, nbytes
);
407 buflen
= min(buflen
, MAXBSIZE
);
408 buf
= kmalloc(buflen
, M_TEMP
, M_WAITOK
);
412 aiov
.iov_len
= buflen
;
413 auio
.uio_iov
= &aiov
;
415 auio
.uio_rw
= UIO_READ
;
416 auio
.uio_segflg
= UIO_SYSSPACE
;
418 auio
.uio_resid
= buflen
;
419 auio
.uio_offset
= off
;
422 kfree(cookies
, M_TEMP
);
428 if ((error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
, &ncookies
,
433 outp
= (caddr_t
)args
->dirent
;
435 if (auio
.uio_resid
>= buflen
)
437 len
= buflen
- auio
.uio_resid
;
442 * When using cookies, the vfs has the option of reading from
443 * a different offset than that supplied (UFS truncates the
444 * offset to a block boundary to make sure that it never reads
445 * partway through a directory entry, even if the directory
446 * has been compacted).
448 while (len
> 0 && ncookies
> 0 && *cookiep
< off
) {
449 bdp
= (struct dirent
*) inp
;
450 len
-= _DIRENT_DIRSIZ(bdp
);
451 inp
+= _DIRENT_DIRSIZ(bdp
);
458 if (cookiep
&& ncookies
== 0)
460 bdp
= (struct dirent
*) inp
;
461 reclen
= _DIRENT_DIRSIZ(bdp
);
467 if (bdp
->d_ino
== 0) {
480 linuxreclen
= (is64bit
)
481 ? LINUX_RECLEN(&linux_dirent64
, bdp
->d_namlen
)
482 : LINUX_RECLEN(&linux_dirent
, bdp
->d_namlen
);
484 if (reclen
> len
|| resid
< linuxreclen
) {
489 bzero(&linux_dirent
, sizeof(linux_dirent
));
490 bzero(&linux_dirent64
, sizeof(linux_dirent64
));
492 /* readdir(2) case. */
493 linux_dirent
.d_ino
= (l_long
)INO64TO32(bdp
->d_ino
);
494 linux_dirent
.d_off
= (l_off_t
)linuxreclen
;
495 linux_dirent
.d_reclen
= (l_ushort
)bdp
->d_namlen
;
496 strcpy(linux_dirent
.d_name
, bdp
->d_name
);
497 error
= copyout(&linux_dirent
, outp
, linuxreclen
);
500 linux_dirent64
.d_ino
= INO64TO32(bdp
->d_ino
);
501 linux_dirent64
.d_off
= (cookiep
)
503 : (l_off_t
)(off
+ reclen
);
504 linux_dirent64
.d_reclen
=
505 (l_ushort
)linuxreclen
;
506 linux_dirent64
.d_type
= bdp
->d_type
;
507 strcpy(linux_dirent64
.d_name
, bdp
->d_name
);
508 error
= copyout(&linux_dirent64
, outp
,
511 linux_dirent
.d_ino
= INO64TO32(bdp
->d_ino
);
512 linux_dirent
.d_off
= (cookiep
)
514 : (l_off_t
)(off
+ reclen
);
515 linux_dirent
.d_reclen
= (l_ushort
)linuxreclen
;
516 strcpy(linux_dirent
.d_name
, bdp
->d_name
);
517 error
= copyout(&linux_dirent
, outp
,
534 resid
-= linuxreclen
;
540 if (outp
== (caddr_t
)args
->dirent
&& eofflag
== 0)
545 nbytes
= resid
+ linuxreclen
;
548 args
->sysmsg_iresult
= (int)(nbytes
- resid
);
552 kfree(cookies
, M_TEMP
);
565 sys_linux_getdents(struct linux_getdents_args
*args
)
568 if (ldebug(getdents
))
569 kprintf(ARGS(getdents
, "%d, *, %d"), args
->fd
, args
->count
);
571 return (getdents_common((struct linux_getdents64_args
*)args
, 0));
578 sys_linux_getdents64(struct linux_getdents64_args
*args
)
581 if (ldebug(getdents64
))
582 kprintf(ARGS(getdents64
, "%d, *, %d"), args
->fd
, args
->count
);
584 return (getdents_common(args
, 1));
588 * These exist mainly for hooks for doing /compat/linux translation.
593 sys_linux_access(struct linux_access_args
*args
)
595 struct nlookupdata nd
;
599 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
604 kprintf(ARGS(access
, "%s, %d"), path
, args
->flags
);
607 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
609 error
= kern_access(&nd
, args
->flags
, 0);
612 linux_free_path(&path
);
620 sys_linux_unlink(struct linux_unlink_args
*args
)
622 struct nlookupdata nd
;
626 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
631 kprintf(ARGS(unlink
, "%s"), path
);
634 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, 0);
636 error
= kern_unlink(&nd
);
639 linux_free_path(&path
);
644 sys_linux_unlinkat(struct linux_unlinkat_args
*args
)
646 struct nlookupdata nd
;
651 if (args
->flag
& ~LINUX_AT_REMOVEDIR
)
654 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
656 kprintf("linux_copyin_path says error = %d\n", error
);
661 kprintf(ARGS(unlink
, "%s"), path
);
664 dfd
= (args
->dfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->dfd
;
666 error
= nlookup_init_at(&nd
, &fp
, dfd
, path
, UIO_SYSSPACE
, 0);
668 if (args
->flag
& LINUX_AT_REMOVEDIR
)
669 error
= kern_rmdir(&nd
);
671 error
= kern_unlink(&nd
);
673 nlookup_done_at(&nd
, fp
);
675 linux_free_path(&path
);
683 sys_linux_chdir(struct linux_chdir_args
*args
)
685 struct nlookupdata nd
;
689 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
694 kprintf(ARGS(chdir
, "%s"), path
);
697 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
699 error
= kern_chdir(&nd
);
703 linux_free_path(&path
);
711 sys_linux_chmod(struct linux_chmod_args
*args
)
713 struct nlookupdata nd
;
717 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
722 kprintf(ARGS(chmod
, "%s, %d"), path
, args
->mode
);
725 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
727 error
= kern_chmod(&nd
, args
->mode
);
730 linux_free_path(&path
);
738 sys_linux_mkdir(struct linux_mkdir_args
*args
)
740 struct nlookupdata nd
;
744 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_CREATE
);
749 kprintf(ARGS(mkdir
, "%s, %d"), path
, args
->mode
);
752 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, 0);
754 error
= kern_mkdir(&nd
, args
->mode
);
758 linux_free_path(&path
);
763 sys_linux_mkdirat(struct linux_mkdirat_args
*args
)
765 struct nlookupdata nd
;
770 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_CREATE
);
775 kprintf(ARGS(mkdir
, "%s, %d"), path
, args
->mode
);
777 dfd
= (args
->dfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->dfd
;
779 error
= nlookup_init_at(&nd
, &fp
, dfd
, path
, UIO_SYSSPACE
, 0);
781 error
= kern_mkdir(&nd
, args
->mode
);
782 nlookup_done_at(&nd
, fp
);
785 linux_free_path(&path
);
793 sys_linux_rmdir(struct linux_rmdir_args
*args
)
795 struct nlookupdata nd
;
799 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
804 kprintf(ARGS(rmdir
, "%s"), path
);
807 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, 0);
809 error
= kern_rmdir(&nd
);
812 linux_free_path(&path
);
820 sys_linux_rename(struct linux_rename_args
*args
)
822 struct nlookupdata fromnd
, tond
;
826 error
= linux_copyin_path(args
->from
, &from
, LINUX_PATH_EXISTS
);
829 error
= linux_copyin_path(args
->to
, &to
, LINUX_PATH_CREATE
);
831 linux_free_path(&from
);
836 kprintf(ARGS(rename
, "%s, %s"), from
, to
);
839 error
= nlookup_init(&fromnd
, from
, UIO_SYSSPACE
, 0);
841 error
= nlookup_init(&tond
, to
, UIO_SYSSPACE
, 0);
843 error
= kern_rename(&fromnd
, &tond
);
846 nlookup_done(&fromnd
);
848 linux_free_path(&from
);
849 linux_free_path(&to
);
854 sys_linux_renameat(struct linux_renameat_args
*args
)
856 struct nlookupdata fromnd
, tond
;
857 struct file
*fp
, *fp2
;
859 int olddfd
, newdfd
,error
;
861 error
= linux_copyin_path(args
->from
, &from
, LINUX_PATH_EXISTS
);
864 error
= linux_copyin_path(args
->to
, &to
, LINUX_PATH_CREATE
);
866 linux_free_path(&from
);
871 kprintf(ARGS(rename
, "%s, %s"), from
, to
);
873 olddfd
= (args
->olddfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->olddfd
;
874 newdfd
= (args
->newdfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->newdfd
;
876 error
= nlookup_init_at(&fromnd
, &fp
, olddfd
, from
, UIO_SYSSPACE
, 0);
878 error
= nlookup_init_at(&tond
, &fp2
, newdfd
, to
, UIO_SYSSPACE
, 0);
880 error
= kern_rename(&fromnd
, &tond
);
881 nlookup_done_at(&tond
, fp2
);
883 nlookup_done_at(&fromnd
, fp
);
885 linux_free_path(&from
);
886 linux_free_path(&to
);
894 sys_linux_symlink(struct linux_symlink_args
*args
)
896 struct thread
*td
= curthread
;
897 struct nlookupdata nd
;
902 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
905 error
= linux_copyin_path(args
->to
, &link
, LINUX_PATH_CREATE
);
907 linux_free_path(&path
);
912 kprintf(ARGS(symlink
, "%s, %s"), path
, link
);
915 error
= nlookup_init(&nd
, link
, UIO_SYSSPACE
, 0);
917 mode
= ACCESSPERMS
& ~td
->td_proc
->p_fd
->fd_cmask
;
918 error
= kern_symlink(&nd
, path
, mode
);
922 linux_free_path(&path
);
923 linux_free_path(&link
);
928 sys_linux_symlinkat(struct linux_symlinkat_args
*args
)
930 struct thread
*td
= curthread
;
931 struct nlookupdata nd
;
937 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
940 error
= linux_copyin_path(args
->to
, &link
, LINUX_PATH_CREATE
);
942 linux_free_path(&path
);
947 kprintf(ARGS(symlink
, "%s, %s"), path
, link
);
949 newdfd
= (args
->newdfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->newdfd
;
951 error
= nlookup_init_at(&nd
, &fp
, newdfd
, link
, UIO_SYSSPACE
, 0);
953 mode
= ACCESSPERMS
& ~td
->td_proc
->p_fd
->fd_cmask
;
954 error
= kern_symlink(&nd
, path
, mode
);
956 nlookup_done_at(&nd
, fp
);
958 linux_free_path(&path
);
959 linux_free_path(&link
);
967 sys_linux_readlink(struct linux_readlink_args
*args
)
969 struct nlookupdata nd
;
973 error
= linux_copyin_path(args
->name
, &path
, LINUX_PATH_EXISTS
);
977 if (ldebug(readlink
))
978 kprintf(ARGS(readlink
, "%s, %p, %d"), path
, (void *)args
->buf
,
982 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, 0);
984 error
= kern_readlink(&nd
, args
->buf
, args
->count
,
985 &args
->sysmsg_iresult
);
989 linux_free_path(&path
);
994 sys_linux_readlinkat(struct linux_readlinkat_args
*args
)
996 struct nlookupdata nd
;
1001 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
1005 if (ldebug(readlink
))
1006 kprintf(ARGS(readlink
, "%s, %p, %d"), path
, (void *)args
->buf
,
1009 dfd
= (args
->dfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->dfd
;
1011 error
= nlookup_init_at(&nd
, &fp
, dfd
, path
, UIO_SYSSPACE
, 0);
1013 error
= kern_readlink(&nd
, args
->buf
, args
->count
,
1014 &args
->sysmsg_iresult
);
1016 nlookup_done_at(&nd
, fp
);
1018 linux_free_path(&path
);
1026 sys_linux_truncate(struct linux_truncate_args
*args
)
1028 struct nlookupdata nd
;
1032 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
1036 if (ldebug(truncate
))
1037 kprintf(ARGS(truncate
, "%s, %ld"), path
,
1038 (long)args
->length
);
1041 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
1043 error
= kern_truncate(&nd
, args
->length
);
1046 linux_free_path(&path
);
1054 sys_linux_truncate64(struct linux_truncate64_args
*args
)
1056 struct nlookupdata nd
;
1060 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
1064 if (ldebug(truncate64
))
1065 kprintf(ARGS(truncate64
, "%s, %lld"), path
,
1066 (off_t
)args
->length
);
1069 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
1071 error
= kern_truncate(&nd
, args
->length
);
1074 linux_free_path(&path
);
1082 sys_linux_ftruncate(struct linux_ftruncate_args
*args
)
1087 if (ldebug(ftruncate
))
1088 kprintf(ARGS(ftruncate
, "%d, %ld"), args
->fd
,
1089 (long)args
->length
);
1092 error
= kern_ftruncate(args
->fd
, args
->length
);
1102 sys_linux_ftruncate64(struct linux_ftruncate64_args
*args
)
1107 if (ldebug(ftruncate
))
1108 kprintf(ARGS(ftruncate64
, "%d, %lld"), args
->fd
,
1109 (off_t
)args
->length
);
1112 error
= kern_ftruncate(args
->fd
, args
->length
);
1122 sys_linux_link(struct linux_link_args
*args
)
1124 struct nlookupdata nd
, linknd
;
1128 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
1131 error
= linux_copyin_path(args
->to
, &link
, LINUX_PATH_CREATE
);
1133 linux_free_path(&path
);
1138 kprintf(ARGS(link
, "%s, %s"), path
, link
);
1141 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
1143 error
= nlookup_init(&linknd
, link
, UIO_SYSSPACE
, 0);
1145 error
= kern_link(&nd
, &linknd
);
1146 nlookup_done(&linknd
);
1150 linux_free_path(&path
);
1151 linux_free_path(&link
);
1156 sys_linux_linkat(struct linux_linkat_args
*args
)
1158 struct nlookupdata nd
, linknd
;
1159 struct file
*fp
, *fp2
;
1161 int olddfd
, newdfd
, error
;
1163 if (args
->flags
!= 0)
1166 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
1169 error
= linux_copyin_path(args
->to
, &link
, LINUX_PATH_CREATE
);
1171 linux_free_path(&path
);
1176 kprintf(ARGS(link
, "%s, %s"), path
, link
);
1178 olddfd
= (args
->olddfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->olddfd
;
1179 newdfd
= (args
->newdfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->newdfd
;
1181 error
= nlookup_init_at(&nd
, &fp
, olddfd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
1183 error
= nlookup_init_at(&linknd
, &fp2
, newdfd
, link
, UIO_SYSSPACE
, 0);
1185 error
= kern_link(&nd
, &linknd
);
1186 nlookup_done_at(&linknd
, fp2
);
1188 nlookup_done_at(&nd
, fp
);
1190 linux_free_path(&path
);
1191 linux_free_path(&link
);
1199 sys_linux_fdatasync(struct linux_fdatasync_args
*uap
)
1201 struct fsync_args bsd
;
1205 bsd
.sysmsg_iresult
= 0;
1207 error
= sys_fsync(&bsd
);
1208 uap
->sysmsg_iresult
= bsd
.sysmsg_iresult
;
1216 sys_linux_pread(struct linux_pread_args
*uap
)
1218 struct thread
*td
= curthread
;
1223 aiov
.iov_base
= uap
->buf
;
1224 aiov
.iov_len
= uap
->nbyte
;
1225 auio
.uio_iov
= &aiov
;
1226 auio
.uio_iovcnt
= 1;
1227 auio
.uio_offset
= uap
->offset
;
1228 auio
.uio_resid
= uap
->nbyte
;
1229 auio
.uio_rw
= UIO_READ
;
1230 auio
.uio_segflg
= UIO_USERSPACE
;
1233 if ((ssize_t
)auio
.uio_resid
< 0) {
1236 error
= kern_preadv(uap
->fd
, &auio
, O_FOFFSET
,
1237 &uap
->sysmsg_szresult
);
1246 sys_linux_pwrite(struct linux_pwrite_args
*uap
)
1248 struct thread
*td
= curthread
;
1253 aiov
.iov_base
= uap
->buf
;
1254 aiov
.iov_len
= uap
->nbyte
;
1255 auio
.uio_iov
= &aiov
;
1256 auio
.uio_iovcnt
= 1;
1257 auio
.uio_offset
= uap
->offset
;
1258 auio
.uio_resid
= uap
->nbyte
;
1259 auio
.uio_rw
= UIO_WRITE
;
1260 auio
.uio_segflg
= UIO_USERSPACE
;
1263 if ((ssize_t
)auio
.uio_resid
< 0) {
1266 error
= kern_pwritev(uap
->fd
, &auio
, O_FOFFSET
,
1267 &uap
->sysmsg_szresult
);
1276 sys_linux_oldumount(struct linux_oldumount_args
*args
)
1278 struct linux_umount_args args2
;
1281 args2
.path
= args
->path
;
1283 args2
.sysmsg_iresult
= 0;
1284 error
= sys_linux_umount(&args2
);
1285 args
->sysmsg_iresult
= args2
.sysmsg_iresult
;
1293 sys_linux_umount(struct linux_umount_args
*args
)
1295 struct unmount_args bsd
;
1298 bsd
.path
= args
->path
;
1299 bsd
.flags
= args
->flags
; /* XXX correct? */
1300 bsd
.sysmsg_iresult
= 0;
1302 error
= sys_unmount(&bsd
);
1303 args
->sysmsg_iresult
= bsd
.sysmsg_iresult
;
1308 * fcntl family of syscalls
1322 linux_to_bsd_flock(struct l_flock
*linux_flock
, struct flock
*bsd_flock
)
1324 switch (linux_flock
->l_type
) {
1326 bsd_flock
->l_type
= F_RDLCK
;
1329 bsd_flock
->l_type
= F_WRLCK
;
1332 bsd_flock
->l_type
= F_UNLCK
;
1335 bsd_flock
->l_type
= -1;
1338 bsd_flock
->l_whence
= linux_flock
->l_whence
;
1339 bsd_flock
->l_start
= (off_t
)linux_flock
->l_start
;
1340 bsd_flock
->l_len
= (off_t
)linux_flock
->l_len
;
1341 bsd_flock
->l_pid
= (pid_t
)linux_flock
->l_pid
;
1348 bsd_to_linux_flock(struct flock
*bsd_flock
, struct l_flock
*linux_flock
)
1350 switch (bsd_flock
->l_type
) {
1352 linux_flock
->l_type
= LINUX_F_RDLCK
;
1355 linux_flock
->l_type
= LINUX_F_WRLCK
;
1358 linux_flock
->l_type
= LINUX_F_UNLCK
;
1361 linux_flock
->l_whence
= bsd_flock
->l_whence
;
1362 linux_flock
->l_start
= (l_off_t
)bsd_flock
->l_start
;
1363 linux_flock
->l_len
= (l_off_t
)bsd_flock
->l_len
;
1364 linux_flock
->l_pid
= (l_pid_t
)bsd_flock
->l_pid
;
1367 #if defined(__i386__)
1380 linux_to_bsd_flock64(struct l_flock64
*linux_flock
, struct flock
*bsd_flock
)
1382 switch (linux_flock
->l_type
) {
1384 bsd_flock
->l_type
= F_RDLCK
;
1387 bsd_flock
->l_type
= F_WRLCK
;
1390 bsd_flock
->l_type
= F_UNLCK
;
1393 bsd_flock
->l_type
= -1;
1396 bsd_flock
->l_whence
= linux_flock
->l_whence
;
1397 bsd_flock
->l_start
= (off_t
)linux_flock
->l_start
;
1398 bsd_flock
->l_len
= (off_t
)linux_flock
->l_len
;
1399 bsd_flock
->l_pid
= (pid_t
)linux_flock
->l_pid
;
1406 bsd_to_linux_flock64(struct flock
*bsd_flock
, struct l_flock64
*linux_flock
)
1408 switch (bsd_flock
->l_type
) {
1410 linux_flock
->l_type
= LINUX_F_RDLCK
;
1413 linux_flock
->l_type
= LINUX_F_WRLCK
;
1416 linux_flock
->l_type
= LINUX_F_UNLCK
;
1419 linux_flock
->l_whence
= bsd_flock
->l_whence
;
1420 linux_flock
->l_start
= (l_loff_t
)bsd_flock
->l_start
;
1421 linux_flock
->l_len
= (l_loff_t
)bsd_flock
->l_len
;
1422 linux_flock
->l_pid
= (l_pid_t
)bsd_flock
->l_pid
;
1424 #endif /* __i386__ */
1430 linux_fcntl_common(struct linux_fcntl64_args
*args
)
1432 struct thread
*td
= curthread
;
1433 struct l_flock linux_flock
;
1435 union fcntl_dat dat
;
1438 switch (args
->cmd
) {
1441 dat
.fc_fd
= args
->arg
;
1448 dat
.fc_cloexec
= args
->arg
;
1456 if (args
->arg
& LINUX_O_NDELAY
)
1457 dat
.fc_flags
|= O_NONBLOCK
;
1458 if (args
->arg
& LINUX_O_APPEND
)
1459 dat
.fc_flags
|= O_APPEND
;
1460 if (args
->arg
& LINUX_O_SYNC
)
1461 dat
.fc_flags
|= O_FSYNC
;
1462 if (args
->arg
& LINUX_FASYNC
)
1463 dat
.fc_flags
|= O_ASYNC
;
1467 case LINUX_F_SETLKW
:
1469 error
= copyin((caddr_t
)args
->arg
, &linux_flock
,
1470 sizeof(linux_flock
));
1473 linux_to_bsd_flock(&linux_flock
, &dat
.fc_flock
);
1475 case LINUX_F_GETOWN
:
1478 case LINUX_F_SETOWN
:
1480 * XXX some Linux applications depend on F_SETOWN having no
1481 * significant effect for pipes (SIGIO is not delivered for
1482 * pipes under Linux-2.2.35 at least).
1484 fp
= holdfp(td
->td_proc
->p_fd
, args
->fd
, -1);
1487 if (fp
->f_type
== DTYPE_PIPE
) {
1493 dat
.fc_owner
= args
->arg
;
1500 error
= kern_fcntl(args
->fd
, cmd
, &dat
, td
->td_ucred
);
1503 switch (args
->cmd
) {
1505 args
->sysmsg_iresult
= dat
.fc_fd
;
1508 args
->sysmsg_iresult
= dat
.fc_cloexec
;
1513 args
->sysmsg_iresult
= 0;
1514 if (dat
.fc_flags
& O_RDONLY
)
1515 args
->sysmsg_iresult
|= LINUX_O_RDONLY
;
1516 if (dat
.fc_flags
& O_WRONLY
)
1517 args
->sysmsg_iresult
|= LINUX_O_WRONLY
;
1518 if (dat
.fc_flags
& O_RDWR
)
1519 args
->sysmsg_iresult
|= LINUX_O_RDWR
;
1520 if (dat
.fc_flags
& O_NDELAY
)
1521 args
->sysmsg_iresult
|= LINUX_O_NONBLOCK
;
1522 if (dat
.fc_flags
& O_APPEND
)
1523 args
->sysmsg_iresult
|= LINUX_O_APPEND
;
1524 if (dat
.fc_flags
& O_FSYNC
)
1525 args
->sysmsg_iresult
|= LINUX_O_SYNC
;
1526 if (dat
.fc_flags
& O_ASYNC
)
1527 args
->sysmsg_iresult
|= LINUX_FASYNC
;
1530 bsd_to_linux_flock(&dat
.fc_flock
, &linux_flock
);
1531 error
= copyout(&linux_flock
, (caddr_t
)args
->arg
,
1532 sizeof(linux_flock
));
1535 case LINUX_F_SETLKW
:
1537 case LINUX_F_GETOWN
:
1538 args
->sysmsg_iresult
= dat
.fc_owner
;
1540 case LINUX_F_SETOWN
:
1552 sys_linux_fcntl(struct linux_fcntl_args
*args
)
1554 struct linux_fcntl64_args args64
;
1559 kprintf(ARGS(fcntl
, "%d, %08x, *"), args
->fd
, args
->cmd
);
1562 args64
.fd
= args
->fd
;
1563 args64
.cmd
= args
->cmd
;
1564 args64
.arg
= args
->arg
;
1565 args64
.sysmsg_iresult
= 0;
1566 error
= linux_fcntl_common(&args64
);
1567 args
->sysmsg_iresult
= args64
.sysmsg_iresult
;
1571 #if defined(__i386__)
1576 sys_linux_fcntl64(struct linux_fcntl64_args
*args
)
1578 struct thread
*td
= curthread
;
1579 struct l_flock64 linux_flock
;
1580 union fcntl_dat dat
;
1584 if (ldebug(fcntl64
))
1585 kprintf(ARGS(fcntl64
, "%d, %08x, *"), args
->fd
, args
->cmd
);
1587 if (args
->cmd
== LINUX_F_GETLK64
|| args
->cmd
== LINUX_F_SETLK64
||
1588 args
->cmd
== LINUX_F_SETLKW64
) {
1589 switch (args
->cmd
) {
1590 case LINUX_F_GETLK64
:
1593 case LINUX_F_SETLK64
:
1596 case LINUX_F_SETLKW64
:
1601 error
= copyin((caddr_t
)args
->arg
, &linux_flock
,
1602 sizeof(linux_flock
));
1605 linux_to_bsd_flock64(&linux_flock
, &dat
.fc_flock
);
1608 error
= kern_fcntl(args
->fd
, cmd
, &dat
, td
->td_ucred
);
1610 if (error
== 0 && args
->cmd
== LINUX_F_GETLK64
) {
1611 bsd_to_linux_flock64(&dat
.fc_flock
, &linux_flock
);
1612 error
= copyout(&linux_flock
, (caddr_t
)args
->arg
,
1613 sizeof(linux_flock
));
1616 error
= linux_fcntl_common(args
);
1621 #endif /* __i386__ */
1627 sys_linux_chown(struct linux_chown_args
*args
)
1629 struct nlookupdata nd
;
1633 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
1638 kprintf(ARGS(chown
, "%s, %d, %d"), path
, args
->uid
, args
->gid
);
1641 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
);
1643 error
= kern_chown(&nd
, args
->uid
, args
->gid
);
1646 linux_free_path(&path
);
1654 sys_linux_lchown(struct linux_lchown_args
*args
)
1656 struct nlookupdata nd
;
1660 error
= linux_copyin_path(args
->path
, &path
, LINUX_PATH_EXISTS
);
1665 kprintf(ARGS(lchown
, "%s, %d, %d"), path
, args
->uid
, args
->gid
);
1668 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, 0);
1670 error
= kern_chown(&nd
, args
->uid
, args
->gid
);
1673 linux_free_path(&path
);
1678 sys_linux_fchmodat(struct linux_fchmodat_args
*args
)
1680 struct fchmodat_args uap
;
1683 uap
.fd
= (args
->dfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->dfd
;
1684 uap
.path
= args
->filename
;
1685 uap
.mode
= args
->mode
;
1688 error
= sys_fchmodat(&uap
);
1694 sys_linux_fchownat(struct linux_fchownat_args
*args
)
1696 struct fchownat_args uap
;
1699 if (args
->flag
& ~LINUX_AT_SYMLINK_NOFOLLOW
)
1702 uap
.fd
= (args
->dfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->dfd
;
1703 uap
.path
= args
->filename
;
1704 uap
.uid
= args
->uid
;
1705 uap
.gid
= args
->gid
;
1706 uap
.flags
= (args
->flag
& LINUX_AT_SYMLINK_NOFOLLOW
) == 0 ? 0 :
1707 AT_SYMLINK_NOFOLLOW
;
1709 error
= sys_fchownat(&uap
);
1715 sys_linux_faccessat(struct linux_faccessat_args
*args
)
1717 struct faccessat_args uap
;
1720 uap
.fd
= (args
->dfd
== LINUX_AT_FDCWD
) ? AT_FDCWD
: args
->dfd
;
1721 uap
.path
= args
->filename
;
1722 uap
.amode
= args
->mode
;
1725 error
= sys_faccessat(&uap
);