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);