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 without 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);
79 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
81 error = kern_open(&nd, O_WRONLY | O_CREAT | O_TRUNC,
82 args->mode, &args->sysmsg_iresult);
84 linux_free_path(&path);
92 linux_open_common(int dfd, char *lpath, int lflags, int mode, int *iresult)
94 struct thread *td = curthread;
95 struct proc *p = td->td_proc;
96 struct nlookupdata nd;
101 if (lflags & LINUX_O_CREAT) {
102 error = linux_copyin_path(lpath, &path,
105 error = linux_copyin_path(lpath, &path,
112 if (lflags & LINUX_O_RDONLY)
114 if (lflags & LINUX_O_WRONLY)
116 if (lflags & LINUX_O_RDWR)
118 if (lflags & LINUX_O_NDELAY)
120 if (lflags & LINUX_O_APPEND)
122 if (lflags & LINUX_O_SYNC)
124 if (lflags & LINUX_O_NONBLOCK)
126 if (lflags & LINUX_FASYNC)
128 if (lflags & LINUX_O_CREAT)
130 if (lflags & LINUX_O_TRUNC)
132 if (lflags & LINUX_O_EXCL)
134 if (lflags & LINUX_O_NOCTTY)
137 error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, NLC_FOLLOW);
139 error = kern_open(&nd, flags, mode, iresult);
141 nlookup_done_at(&nd, fp);
143 if (error == 0 && !(flags & O_NOCTTY) &&
144 SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
147 fp = holdfp(p->p_fd, *iresult, -1);
149 if (fp->f_type == DTYPE_VNODE) {
150 fo_ioctl(fp, TIOCSCTTY, NULL,
157 if (error == 0 && lflags & LINUX_O_DIRECTORY) {
161 fp = holdfp(p->p_fd, *iresult, -1);
163 vp = (struct vnode *) fp->f_data;
164 if (vp->v_type != VDIR)
169 kern_close(*iresult);
173 linux_free_path(&path);
178 sys_linux_open(struct linux_open_args *args)
184 kprintf(ARGS(open, "%s, 0x%x, 0x%x"), args->path, args->flags,
188 error = linux_open_common(AT_FDCWD, args->path, args->flags,
189 args->mode, &args->sysmsg_iresult);
193 kprintf(LMSG("open returns error %d"), error);
199 sys_linux_openat(struct linux_openat_args *args)
206 kprintf(ARGS(openat, "%s, 0x%x, 0x%x"), args->path,
207 args->flags, args->mode);
210 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
212 error = linux_open_common(dfd, args->path, args->flags,
213 args->mode, &args->sysmsg_iresult);
217 kprintf(LMSG("openat returns error %d"), error);
226 sys_linux_lseek(struct linux_lseek_args *args)
232 kprintf(ARGS(lseek, "%d, %ld, %d"),
233 args->fdes, (long)args->off, args->whence);
235 error = kern_lseek(args->fdes, args->off, args->whence,
236 &args->sysmsg_offset);
245 sys_linux_llseek(struct linux_llseek_args *args)
252 kprintf(ARGS(llseek, "%d, %d:%d, %d"),
253 args->fd, args->ohigh, args->olow, args->whence);
255 off = (args->olow) | (((off_t) args->ohigh) << 32);
257 error = kern_lseek(args->fd, off, args->whence, &res);
260 error = copyout(&res, args->res, sizeof(res));
268 sys_linux_readdir(struct linux_readdir_args *args)
270 struct linux_getdents_args lda;
274 lda.dent = args->dent;
276 lda.sysmsg_iresult = 0;
277 error = sys_linux_getdents(&lda);
278 args->sysmsg_iresult = lda.sysmsg_iresult;
283 * Note that linux_getdents(2) and linux_getdents64(2) have the same
284 * arguments. They only differ in the definition of struct dirent they
285 * operate on. We use this to common the code, with the exception of
286 * accessing struct dirent. Note that linux_readdir(2) is implemented
287 * by means of linux_getdents(2). In this case we never operate on
288 * struct dirent64 and thus don't need to handle it...
295 char d_name[LINUX_NAME_MAX + 1];
303 char d_name[LINUX_NAME_MAX + 1];
306 #define LINUX_RECLEN(de,namlen) \
307 ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
309 #define LINUX_DIRBLKSIZ 512
315 getdents_common(struct linux_getdents64_args *args, int is64bit)
317 struct thread *td = curthread;
318 struct proc *p = td->td_proc;
321 caddr_t inp, buf; /* BSD-format */
322 int reclen; /* BSD-format */
324 caddr_t outp; /* Linux-format */
325 int linuxreclen = 0; /* Linux-format */
332 struct l_dirent linux_dirent;
333 struct l_dirent64 linux_dirent64;
334 int error, eofflag, justone;
335 size_t buflen, nbytes;
336 off_t *cookies = NULL, *cookiep;
339 if ((error = holdvnode(p->p_fd, args->fd, &fp)) != 0)
343 if ((fp->f_flag & FREAD) == 0) {
348 vp = (struct vnode *) fp->f_data;
349 if (vp->v_type != VDIR) {
354 if ((error = VOP_GETATTR(vp, &va)) != 0)
357 nbytes = args->count;
358 if (nbytes == (size_t)-1) {
359 /* readdir(2) case. Always struct dirent. */
364 nbytes = sizeof(linux_dirent);
369 if ((size_t)nbytes < 0)
374 buflen = max(LINUX_DIRBLKSIZ, nbytes);
375 buflen = min(buflen, MAXBSIZE);
376 buf = kmalloc(buflen, M_TEMP, M_WAITOK);
380 aiov.iov_len = buflen;
381 auio.uio_iov = &aiov;
383 auio.uio_rw = UIO_READ;
384 auio.uio_segflg = UIO_SYSSPACE;
386 auio.uio_resid = buflen;
387 auio.uio_offset = off;
390 kfree(cookies, M_TEMP);
396 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
401 outp = (caddr_t)args->dirent;
403 if (auio.uio_resid >= buflen)
405 len = buflen - auio.uio_resid;
410 * When using cookies, the vfs has the option of reading from
411 * a different offset than that supplied (UFS truncates the
412 * offset to a block boundary to make sure that it never reads
413 * partway through a directory entry, even if the directory
414 * has been compacted).
416 while (len > 0 && ncookies > 0 && *cookiep < off) {
417 bdp = (struct dirent *) inp;
418 len -= _DIRENT_DIRSIZ(bdp);
419 inp += _DIRENT_DIRSIZ(bdp);
426 if (cookiep && ncookies == 0)
428 bdp = (struct dirent *) inp;
429 reclen = _DIRENT_DIRSIZ(bdp);
435 if (bdp->d_ino == 0) {
448 linuxreclen = (is64bit)
449 ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen)
450 : LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
452 if (reclen > len || resid < linuxreclen) {
457 bzero(&linux_dirent, sizeof(linux_dirent));
458 bzero(&linux_dirent64, sizeof(linux_dirent64));
460 /* readdir(2) case. */
461 linux_dirent.d_ino = (l_long)INO64TO32(bdp->d_ino);
462 linux_dirent.d_off = (l_off_t)linuxreclen;
463 linux_dirent.d_reclen = (l_ushort)bdp->d_namlen;
464 strcpy(linux_dirent.d_name, bdp->d_name);
465 error = copyout(&linux_dirent, outp, linuxreclen);
468 linux_dirent64.d_ino = INO64TO32(bdp->d_ino);
469 linux_dirent64.d_off = (cookiep)
471 : (l_off_t)(off + reclen);
472 linux_dirent64.d_reclen =
473 (l_ushort)linuxreclen;
474 linux_dirent64.d_type = bdp->d_type;
475 strcpy(linux_dirent64.d_name, bdp->d_name);
476 error = copyout(&linux_dirent64, outp,
479 linux_dirent.d_ino = INO64TO32(bdp->d_ino);
480 linux_dirent.d_off = (cookiep)
482 : (l_off_t)(off + reclen);
483 linux_dirent.d_reclen = (l_ushort)linuxreclen;
484 strcpy(linux_dirent.d_name, bdp->d_name);
485 error = copyout(&linux_dirent, outp,
502 resid -= linuxreclen;
508 if (outp == (caddr_t)args->dirent && eofflag == 0)
513 nbytes = resid + linuxreclen;
516 args->sysmsg_iresult = (int)(nbytes - resid);
520 kfree(cookies, M_TEMP);
533 sys_linux_getdents(struct linux_getdents_args *args)
536 if (ldebug(getdents))
537 kprintf(ARGS(getdents, "%d, *, %d"), args->fd, args->count);
539 return (getdents_common((struct linux_getdents64_args*)args, 0));
546 sys_linux_getdents64(struct linux_getdents64_args *args)
549 if (ldebug(getdents64))
550 kprintf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count);
552 return (getdents_common(args, 1));
556 * These exist mainly for hooks for doing /compat/linux translation.
561 sys_linux_access(struct linux_access_args *args)
563 struct nlookupdata nd;
567 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
572 kprintf(ARGS(access, "%s, %d"), path, args->flags);
575 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
577 error = kern_access(&nd, args->flags, 0);
580 linux_free_path(&path);
588 sys_linux_unlink(struct linux_unlink_args *args)
590 struct nlookupdata nd;
594 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
599 kprintf(ARGS(unlink, "%s"), path);
602 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
604 error = kern_unlink(&nd);
607 linux_free_path(&path);
612 sys_linux_unlinkat(struct linux_unlinkat_args *args)
614 struct nlookupdata nd;
619 if (args->flag & ~LINUX_AT_REMOVEDIR)
622 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
624 kprintf("linux_copyin_path says error = %d\n", error);
629 kprintf(ARGS(unlink, "%s"), path);
632 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
634 error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
636 if (args->flag & LINUX_AT_REMOVEDIR)
637 error = kern_rmdir(&nd);
639 error = kern_unlink(&nd);
641 nlookup_done_at(&nd, fp);
643 linux_free_path(&path);
651 sys_linux_chdir(struct linux_chdir_args *args)
653 struct nlookupdata nd;
657 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
662 kprintf(ARGS(chdir, "%s"), path);
665 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
667 error = kern_chdir(&nd);
671 linux_free_path(&path);
679 sys_linux_chmod(struct linux_chmod_args *args)
681 struct nlookupdata nd;
685 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
690 kprintf(ARGS(chmod, "%s, %d"), path, args->mode);
693 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
695 error = kern_chmod(&nd, args->mode);
698 linux_free_path(&path);
706 sys_linux_mkdir(struct linux_mkdir_args *args)
708 struct nlookupdata nd;
712 error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
717 kprintf(ARGS(mkdir, "%s, %d"), path, args->mode);
720 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
722 error = kern_mkdir(&nd, args->mode);
726 linux_free_path(&path);
731 sys_linux_mkdirat(struct linux_mkdirat_args *args)
733 struct nlookupdata nd;
738 error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
743 kprintf(ARGS(mkdir, "%s, %d"), path, args->mode);
745 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
747 error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
749 error = kern_mkdir(&nd, args->mode);
750 nlookup_done_at(&nd, fp);
753 linux_free_path(&path);
761 sys_linux_rmdir(struct linux_rmdir_args *args)
763 struct nlookupdata nd;
767 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
772 kprintf(ARGS(rmdir, "%s"), path);
775 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
777 error = kern_rmdir(&nd);
780 linux_free_path(&path);
788 sys_linux_rename(struct linux_rename_args *args)
790 struct nlookupdata fromnd, tond;
794 error = linux_copyin_path(args->from, &from, LINUX_PATH_EXISTS);
797 error = linux_copyin_path(args->to, &to, LINUX_PATH_CREATE);
799 linux_free_path(&from);
804 kprintf(ARGS(rename, "%s, %s"), from, to);
807 error = nlookup_init(&fromnd, from, UIO_SYSSPACE, 0);
809 error = nlookup_init(&tond, to, UIO_SYSSPACE, 0);
811 error = kern_rename(&fromnd, &tond);
814 nlookup_done(&fromnd);
816 linux_free_path(&from);
817 linux_free_path(&to);
822 sys_linux_renameat(struct linux_renameat_args *args)
824 struct nlookupdata fromnd, tond;
825 struct file *fp, *fp2;
827 int olddfd, newdfd,error;
829 error = linux_copyin_path(args->from, &from, LINUX_PATH_EXISTS);
832 error = linux_copyin_path(args->to, &to, LINUX_PATH_CREATE);
834 linux_free_path(&from);
839 kprintf(ARGS(rename, "%s, %s"), from, to);
841 olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
842 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
844 error = nlookup_init_at(&fromnd, &fp, olddfd, from, UIO_SYSSPACE, 0);
846 error = nlookup_init_at(&tond, &fp2, newdfd, to, UIO_SYSSPACE, 0);
848 error = kern_rename(&fromnd, &tond);
849 nlookup_done_at(&tond, fp2);
851 nlookup_done_at(&fromnd, fp);
853 linux_free_path(&from);
854 linux_free_path(&to);
862 sys_linux_symlink(struct linux_symlink_args *args)
864 struct thread *td = curthread;
865 struct nlookupdata nd;
870 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
873 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
875 linux_free_path(&path);
880 kprintf(ARGS(symlink, "%s, %s"), path, link);
883 error = nlookup_init(&nd, link, UIO_SYSSPACE, 0);
885 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
886 error = kern_symlink(&nd, path, mode);
890 linux_free_path(&path);
891 linux_free_path(&link);
896 sys_linux_symlinkat(struct linux_symlinkat_args *args)
898 struct thread *td = curthread;
899 struct nlookupdata nd;
905 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
908 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
910 linux_free_path(&path);
915 kprintf(ARGS(symlink, "%s, %s"), path, link);
917 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
919 error = nlookup_init_at(&nd, &fp, newdfd, link, UIO_SYSSPACE, 0);
921 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
922 error = kern_symlink(&nd, path, mode);
924 nlookup_done_at(&nd, fp);
926 linux_free_path(&path);
927 linux_free_path(&link);
935 sys_linux_readlink(struct linux_readlink_args *args)
937 struct nlookupdata nd;
941 error = linux_copyin_path(args->name, &path, LINUX_PATH_EXISTS);
945 if (ldebug(readlink))
946 kprintf(ARGS(readlink, "%s, %p, %d"), path, (void *)args->buf,
950 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
952 error = kern_readlink(&nd, args->buf, args->count,
953 &args->sysmsg_iresult);
957 linux_free_path(&path);
962 sys_linux_readlinkat(struct linux_readlinkat_args *args)
964 struct nlookupdata nd;
969 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
973 if (ldebug(readlink))
974 kprintf(ARGS(readlink, "%s, %p, %d"), path, (void *)args->buf,
977 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
979 error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
981 error = kern_readlink(&nd, args->buf, args->count,
982 &args->sysmsg_iresult);
984 nlookup_done_at(&nd, fp);
986 linux_free_path(&path);
994 sys_linux_truncate(struct linux_truncate_args *args)
996 struct nlookupdata nd;
1000 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1004 if (ldebug(truncate))
1005 kprintf(ARGS(truncate, "%s, %ld"), path,
1006 (long)args->length);
1009 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1011 error = kern_truncate(&nd, args->length);
1014 linux_free_path(&path);
1022 sys_linux_truncate64(struct linux_truncate64_args *args)
1024 struct nlookupdata nd;
1028 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1032 if (ldebug(truncate64))
1033 kprintf(ARGS(truncate64, "%s, %lld"), path,
1034 (off_t)args->length);
1037 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1039 error = kern_truncate(&nd, args->length);
1042 linux_free_path(&path);
1050 sys_linux_ftruncate(struct linux_ftruncate_args *args)
1055 if (ldebug(ftruncate))
1056 kprintf(ARGS(ftruncate, "%d, %ld"), args->fd,
1057 (long)args->length);
1060 error = kern_ftruncate(args->fd, args->length);
1070 sys_linux_ftruncate64(struct linux_ftruncate64_args *args)
1075 if (ldebug(ftruncate))
1076 kprintf(ARGS(ftruncate64, "%d, %lld"), args->fd,
1077 (off_t)args->length);
1080 error = kern_ftruncate(args->fd, args->length);
1090 sys_linux_link(struct linux_link_args *args)
1092 struct nlookupdata nd, linknd;
1096 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1099 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
1101 linux_free_path(&path);
1106 kprintf(ARGS(link, "%s, %s"), path, link);
1109 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1111 error = nlookup_init(&linknd, link, UIO_SYSSPACE, 0);
1113 error = kern_link(&nd, &linknd);
1114 nlookup_done(&linknd);
1118 linux_free_path(&path);
1119 linux_free_path(&link);
1124 sys_linux_linkat(struct linux_linkat_args *args)
1126 struct nlookupdata nd, linknd;
1127 struct file *fp, *fp2;
1129 int olddfd, newdfd, error;
1131 if (args->flags != 0)
1134 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1137 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
1139 linux_free_path(&path);
1144 kprintf(ARGS(link, "%s, %s"), path, link);
1146 olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
1147 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
1149 error = nlookup_init_at(&nd, &fp, olddfd, path, UIO_SYSSPACE, NLC_FOLLOW);
1151 error = nlookup_init_at(&linknd, &fp2, newdfd, link, UIO_SYSSPACE, 0);
1153 error = kern_link(&nd, &linknd);
1154 nlookup_done_at(&linknd, fp2);
1156 nlookup_done_at(&nd, fp);
1158 linux_free_path(&path);
1159 linux_free_path(&link);
1167 sys_linux_fdatasync(struct linux_fdatasync_args *uap)
1169 struct fsync_args bsd;
1173 bsd.sysmsg_iresult = 0;
1175 error = sys_fsync(&bsd);
1176 uap->sysmsg_iresult = bsd.sysmsg_iresult;
1184 sys_linux_pread(struct linux_pread_args *uap)
1186 struct thread *td = curthread;
1191 aiov.iov_base = uap->buf;
1192 aiov.iov_len = uap->nbyte;
1193 auio.uio_iov = &aiov;
1194 auio.uio_iovcnt = 1;
1195 auio.uio_offset = uap->offset;
1196 auio.uio_resid = uap->nbyte;
1197 auio.uio_rw = UIO_READ;
1198 auio.uio_segflg = UIO_USERSPACE;
1201 if ((ssize_t)auio.uio_resid < 0) {
1204 error = kern_preadv(uap->fd, &auio, O_FOFFSET,
1205 &uap->sysmsg_szresult);
1214 sys_linux_pwrite(struct linux_pwrite_args *uap)
1216 struct thread *td = curthread;
1221 aiov.iov_base = uap->buf;
1222 aiov.iov_len = uap->nbyte;
1223 auio.uio_iov = &aiov;
1224 auio.uio_iovcnt = 1;
1225 auio.uio_offset = uap->offset;
1226 auio.uio_resid = uap->nbyte;
1227 auio.uio_rw = UIO_WRITE;
1228 auio.uio_segflg = UIO_USERSPACE;
1231 if ((ssize_t)auio.uio_resid < 0) {
1234 error = kern_pwritev(uap->fd, &auio, O_FOFFSET,
1235 &uap->sysmsg_szresult);
1244 sys_linux_oldumount(struct linux_oldumount_args *args)
1246 struct linux_umount_args args2;
1249 args2.path = args->path;
1251 args2.sysmsg_iresult = 0;
1252 error = sys_linux_umount(&args2);
1253 args->sysmsg_iresult = args2.sysmsg_iresult;
1261 sys_linux_umount(struct linux_umount_args *args)
1263 struct unmount_args bsd;
1266 bsd.path = args->path;
1267 bsd.flags = args->flags; /* XXX correct? */
1268 bsd.sysmsg_iresult = 0;
1270 error = sys_unmount(&bsd);
1271 args->sysmsg_iresult = bsd.sysmsg_iresult;
1276 * fcntl family of syscalls
1290 linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
1292 switch (linux_flock->l_type) {
1294 bsd_flock->l_type = F_RDLCK;
1297 bsd_flock->l_type = F_WRLCK;
1300 bsd_flock->l_type = F_UNLCK;
1303 bsd_flock->l_type = -1;
1306 bsd_flock->l_whence = linux_flock->l_whence;
1307 bsd_flock->l_start = (off_t)linux_flock->l_start;
1308 bsd_flock->l_len = (off_t)linux_flock->l_len;
1309 bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1316 bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
1318 switch (bsd_flock->l_type) {
1320 linux_flock->l_type = LINUX_F_RDLCK;
1323 linux_flock->l_type = LINUX_F_WRLCK;
1326 linux_flock->l_type = LINUX_F_UNLCK;
1329 linux_flock->l_whence = bsd_flock->l_whence;
1330 linux_flock->l_start = (l_off_t)bsd_flock->l_start;
1331 linux_flock->l_len = (l_off_t)bsd_flock->l_len;
1332 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
1335 #if defined(__i386__)
1348 linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
1350 switch (linux_flock->l_type) {
1352 bsd_flock->l_type = F_RDLCK;
1355 bsd_flock->l_type = F_WRLCK;
1358 bsd_flock->l_type = F_UNLCK;
1361 bsd_flock->l_type = -1;
1364 bsd_flock->l_whence = linux_flock->l_whence;
1365 bsd_flock->l_start = (off_t)linux_flock->l_start;
1366 bsd_flock->l_len = (off_t)linux_flock->l_len;
1367 bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1374 bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
1376 switch (bsd_flock->l_type) {
1378 linux_flock->l_type = LINUX_F_RDLCK;
1381 linux_flock->l_type = LINUX_F_WRLCK;
1384 linux_flock->l_type = LINUX_F_UNLCK;
1387 linux_flock->l_whence = bsd_flock->l_whence;
1388 linux_flock->l_start = (l_loff_t)bsd_flock->l_start;
1389 linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
1390 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
1392 #endif /* __i386__ */
1398 linux_fcntl_common(struct linux_fcntl64_args *args)
1400 struct thread *td = curthread;
1401 struct l_flock linux_flock;
1403 union fcntl_dat dat;
1406 switch (args->cmd) {
1409 dat.fc_fd = args->arg;
1416 dat.fc_cloexec = args->arg;
1424 if (args->arg & LINUX_O_NDELAY)
1425 dat.fc_flags |= O_NONBLOCK;
1426 if (args->arg & LINUX_O_APPEND)
1427 dat.fc_flags |= O_APPEND;
1428 if (args->arg & LINUX_O_SYNC)
1429 dat.fc_flags |= O_FSYNC;
1430 if (args->arg & LINUX_FASYNC)
1431 dat.fc_flags |= O_ASYNC;
1435 case LINUX_F_SETLKW:
1437 error = copyin((caddr_t)args->arg, &linux_flock,
1438 sizeof(linux_flock));
1441 linux_to_bsd_flock(&linux_flock, &dat.fc_flock);
1443 case LINUX_F_GETOWN:
1446 case LINUX_F_SETOWN:
1448 * XXX some Linux applications depend on F_SETOWN having no
1449 * significant effect for pipes (SIGIO is not delivered for
1450 * pipes under Linux-2.2.35 at least).
1452 fp = holdfp(td->td_proc->p_fd, args->fd, -1);
1455 if (fp->f_type == DTYPE_PIPE) {
1461 dat.fc_owner = args->arg;
1468 error = kern_fcntl(args->fd, cmd, &dat, td->td_ucred);
1471 switch (args->cmd) {
1473 args->sysmsg_iresult = dat.fc_fd;
1476 args->sysmsg_iresult = dat.fc_cloexec;
1481 args->sysmsg_iresult = 0;
1482 if (dat.fc_flags & O_RDONLY)
1483 args->sysmsg_iresult |= LINUX_O_RDONLY;
1484 if (dat.fc_flags & O_WRONLY)
1485 args->sysmsg_iresult |= LINUX_O_WRONLY;
1486 if (dat.fc_flags & O_RDWR)
1487 args->sysmsg_iresult |= LINUX_O_RDWR;
1488 if (dat.fc_flags & O_NDELAY)
1489 args->sysmsg_iresult |= LINUX_O_NONBLOCK;
1490 if (dat.fc_flags & O_APPEND)
1491 args->sysmsg_iresult |= LINUX_O_APPEND;
1492 if (dat.fc_flags & O_FSYNC)
1493 args->sysmsg_iresult |= LINUX_O_SYNC;
1494 if (dat.fc_flags & O_ASYNC)
1495 args->sysmsg_iresult |= LINUX_FASYNC;
1498 bsd_to_linux_flock(&dat.fc_flock, &linux_flock);
1499 error = copyout(&linux_flock, (caddr_t)args->arg,
1500 sizeof(linux_flock));
1503 case LINUX_F_SETLKW:
1505 case LINUX_F_GETOWN:
1506 args->sysmsg_iresult = dat.fc_owner;
1508 case LINUX_F_SETOWN:
1520 sys_linux_fcntl(struct linux_fcntl_args *args)
1522 struct linux_fcntl64_args args64;
1527 kprintf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
1530 args64.fd = args->fd;
1531 args64.cmd = args->cmd;
1532 args64.arg = args->arg;
1533 args64.sysmsg_iresult = 0;
1534 error = linux_fcntl_common(&args64);
1535 args->sysmsg_iresult = args64.sysmsg_iresult;
1539 #if defined(__i386__)
1544 sys_linux_fcntl64(struct linux_fcntl64_args *args)
1546 struct thread *td = curthread;
1547 struct l_flock64 linux_flock;
1548 union fcntl_dat dat;
1552 if (ldebug(fcntl64))
1553 kprintf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd);
1555 if (args->cmd == LINUX_F_GETLK64 || args->cmd == LINUX_F_SETLK64 ||
1556 args->cmd == LINUX_F_SETLKW64) {
1557 switch (args->cmd) {
1558 case LINUX_F_GETLK64:
1561 case LINUX_F_SETLK64:
1564 case LINUX_F_SETLKW64:
1569 error = copyin((caddr_t)args->arg, &linux_flock,
1570 sizeof(linux_flock));
1573 linux_to_bsd_flock64(&linux_flock, &dat.fc_flock);
1576 error = kern_fcntl(args->fd, cmd, &dat, td->td_ucred);
1578 if (error == 0 && args->cmd == LINUX_F_GETLK64) {
1579 bsd_to_linux_flock64(&dat.fc_flock, &linux_flock);
1580 error = copyout(&linux_flock, (caddr_t)args->arg,
1581 sizeof(linux_flock));
1584 error = linux_fcntl_common(args);
1589 #endif /* __i386__ */
1595 sys_linux_chown(struct linux_chown_args *args)
1597 struct nlookupdata nd;
1601 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1606 kprintf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid);
1609 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1611 error = kern_chown(&nd, args->uid, args->gid);
1614 linux_free_path(&path);
1622 sys_linux_lchown(struct linux_lchown_args *args)
1624 struct nlookupdata nd;
1628 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1633 kprintf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid);
1636 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
1638 error = kern_chown(&nd, args->uid, args->gid);
1641 linux_free_path(&path);
1646 sys_linux_fchmodat(struct linux_fchmodat_args *args)
1648 struct fchmodat_args uap;
1651 uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1652 uap.path = args->filename;
1653 uap.mode = args->mode;
1656 error = sys_fchmodat(&uap);
1662 sys_linux_fchownat(struct linux_fchownat_args *args)
1664 struct fchownat_args uap;
1667 if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
1670 uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1671 uap.path = args->filename;
1672 uap.uid = args->uid;
1673 uap.gid = args->gid;
1674 uap.flags = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 :
1675 AT_SYMLINK_NOFOLLOW;
1677 error = sys_fchownat(&uap);
1683 sys_linux_faccessat(struct linux_faccessat_args *args)
1685 struct faccessat_args uap;
1688 uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1689 uap.path = args->filename;
1690 uap.amode = args->mode;
1693 error = sys_faccessat(&uap);