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 $
31 #include "opt_compat.h"
33 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <sys/dirent.h>
37 #include <sys/fcntl.h>
40 #include <sys/filedesc.h>
41 #include <sys/kern_syscall.h>
43 #include <sys/malloc.h>
44 #include <sys/mount.h>
45 #include <sys/nlookup.h>
47 #include <sys/sysproto.h>
49 #include <sys/vnode.h>
51 #include <vfs/ufs/quota.h>
52 #include <vfs/ufs/ufsmount.h>
54 #include <sys/file2.h>
55 #include <sys/mplock2.h>
57 #include <arch_linux/linux.h>
58 #include <arch_linux/linux_proto.h>
59 #include "linux_util.h"
65 sys_linux_creat(struct linux_creat_args *args)
67 struct nlookupdata nd;
71 error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
76 kprintf(ARGS(creat, "%s, %d"), path, args->mode);
78 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
80 error = kern_open(&nd, O_WRONLY | O_CREAT | O_TRUNC,
81 args->mode, &args->sysmsg_iresult);
83 linux_free_path(&path);
91 linux_open_common(int dfd, char *lpath, int lflags, int mode, int *iresult)
93 struct thread *td = curthread;
94 struct proc *p = td->td_proc;
95 struct nlookupdata nd;
100 if (lflags & LINUX_O_CREAT) {
101 error = linux_copyin_path(lpath, &path,
104 error = linux_copyin_path(lpath, &path,
111 if (lflags & LINUX_O_RDONLY)
113 if (lflags & LINUX_O_WRONLY)
115 if (lflags & LINUX_O_RDWR)
117 if (lflags & LINUX_O_NDELAY)
119 if (lflags & LINUX_O_APPEND)
121 if (lflags & LINUX_O_SYNC)
123 if (lflags & LINUX_O_NONBLOCK)
125 if (lflags & LINUX_FASYNC)
127 if (lflags & LINUX_O_CREAT)
129 if (lflags & LINUX_O_TRUNC)
131 if (lflags & LINUX_O_EXCL)
133 if (lflags & LINUX_O_NOCTTY)
136 error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, NLC_FOLLOW);
138 error = kern_open(&nd, flags, mode, iresult);
140 nlookup_done_at(&nd, fp);
142 if (error == 0 && !(flags & O_NOCTTY) &&
143 SESS_LEADER(p) && !(p->p_flags & P_CONTROLT)) {
146 fp = holdfp(p->p_fd, *iresult, -1);
148 if (fp->f_type == DTYPE_VNODE) {
149 fo_ioctl(fp, TIOCSCTTY, NULL,
156 if (error == 0 && lflags & LINUX_O_DIRECTORY) {
160 fp = holdfp(p->p_fd, *iresult, -1);
162 vp = (struct vnode *) fp->f_data;
163 if (vp->v_type != VDIR)
168 kern_close(*iresult);
172 linux_free_path(&path);
177 sys_linux_open(struct linux_open_args *args)
183 kprintf(ARGS(open, "%s, 0x%x, 0x%x"), args->path, args->flags,
187 error = linux_open_common(AT_FDCWD, args->path, args->flags,
188 args->mode, &args->sysmsg_iresult);
192 kprintf(LMSG("open returns error %d"), error);
198 sys_linux_openat(struct linux_openat_args *args)
205 kprintf(ARGS(openat, "%s, 0x%x, 0x%x"), args->path,
206 args->flags, args->mode);
209 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
211 error = linux_open_common(dfd, args->path, args->flags,
212 args->mode, &args->sysmsg_iresult);
216 kprintf(LMSG("openat returns error %d"), error);
225 sys_linux_lseek(struct linux_lseek_args *args)
231 kprintf(ARGS(lseek, "%d, %ld, %d"),
232 args->fdes, (long)args->off, args->whence);
234 error = kern_lseek(args->fdes, args->off, args->whence,
235 &args->sysmsg_offset);
244 sys_linux_llseek(struct linux_llseek_args *args)
251 kprintf(ARGS(llseek, "%d, %d:%d, %d"),
252 args->fd, args->ohigh, args->olow, args->whence);
254 off = (args->olow) | (((off_t) args->ohigh) << 32);
256 error = kern_lseek(args->fd, off, args->whence, &res);
259 error = copyout(&res, args->res, sizeof(res));
267 sys_linux_readdir(struct linux_readdir_args *args)
269 struct linux_getdents_args lda;
273 lda.dent = args->dent;
275 lda.sysmsg_iresult = 0;
276 error = sys_linux_getdents(&lda);
277 args->sysmsg_iresult = lda.sysmsg_iresult;
282 * Note that linux_getdents(2) and linux_getdents64(2) have the same
283 * arguments. They only differ in the definition of struct dirent they
284 * operate on. We use this to common the code, with the exception of
285 * accessing struct dirent. Note that linux_readdir(2) is implemented
286 * by means of linux_getdents(2). In this case we never operate on
287 * struct dirent64 and thus don't need to handle it...
294 char d_name[LINUX_NAME_MAX + 1];
302 char d_name[LINUX_NAME_MAX + 1];
305 #define LINUX_RECLEN(de,namlen) \
306 ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
308 #define LINUX_DIRBLKSIZ 512
314 getdents_common(struct linux_getdents64_args *args, int is64bit)
316 struct thread *td = curthread;
317 struct proc *p = td->td_proc;
320 caddr_t inp, buf; /* BSD-format */
321 int reclen; /* BSD-format */
323 caddr_t outp; /* Linux-format */
324 int linuxreclen = 0; /* Linux-format */
331 struct l_dirent linux_dirent;
332 struct l_dirent64 linux_dirent64;
333 int error, eofflag, justone;
334 size_t buflen, nbytes;
335 off_t *cookies = NULL, *cookiep;
338 if ((error = holdvnode(p->p_fd, args->fd, &fp)) != 0)
342 if ((fp->f_flag & FREAD) == 0) {
347 vp = (struct vnode *) fp->f_data;
348 if (vp->v_type != VDIR) {
353 if ((error = VOP_GETATTR(vp, &va)) != 0)
356 nbytes = args->count;
357 if (nbytes == (size_t)-1) {
358 /* readdir(2) case. Always struct dirent. */
363 nbytes = sizeof(linux_dirent);
368 if ((ssize_t)nbytes < 0)
373 buflen = max(LINUX_DIRBLKSIZ, nbytes);
374 buflen = min(buflen, MAXBSIZE);
375 buf = kmalloc(buflen, M_TEMP, M_WAITOK);
379 aiov.iov_len = buflen;
380 auio.uio_iov = &aiov;
382 auio.uio_rw = UIO_READ;
383 auio.uio_segflg = UIO_SYSSPACE;
385 auio.uio_resid = buflen;
386 auio.uio_offset = off;
389 kfree(cookies, M_TEMP);
395 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
400 outp = (caddr_t)args->dirent;
402 if (auio.uio_resid >= buflen)
404 len = buflen - auio.uio_resid;
409 * When using cookies, the vfs has the option of reading from
410 * a different offset than that supplied (UFS truncates the
411 * offset to a block boundary to make sure that it never reads
412 * partway through a directory entry, even if the directory
413 * has been compacted).
415 while (len > 0 && ncookies > 0 && *cookiep < off) {
416 bdp = (struct dirent *) inp;
417 len -= _DIRENT_DIRSIZ(bdp);
418 inp += _DIRENT_DIRSIZ(bdp);
425 if (cookiep && ncookies == 0)
427 bdp = (struct dirent *) inp;
428 reclen = _DIRENT_DIRSIZ(bdp);
434 if (bdp->d_ino == 0) {
447 linuxreclen = (is64bit)
448 ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen)
449 : LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
451 if (reclen > len || resid < linuxreclen) {
456 bzero(&linux_dirent, sizeof(linux_dirent));
457 bzero(&linux_dirent64, sizeof(linux_dirent64));
459 /* readdir(2) case. */
460 linux_dirent.d_ino = (l_long)INO64TO32(bdp->d_ino);
461 linux_dirent.d_off = (l_off_t)linuxreclen;
462 linux_dirent.d_reclen = (l_ushort)bdp->d_namlen;
463 strcpy(linux_dirent.d_name, bdp->d_name);
464 error = copyout(&linux_dirent, outp, linuxreclen);
467 linux_dirent64.d_ino = INO64TO32(bdp->d_ino);
468 linux_dirent64.d_off = (cookiep)
470 : (l_off_t)(off + reclen);
471 linux_dirent64.d_reclen =
472 (l_ushort)linuxreclen;
473 linux_dirent64.d_type = bdp->d_type;
474 strcpy(linux_dirent64.d_name, bdp->d_name);
475 error = copyout(&linux_dirent64, outp,
478 linux_dirent.d_ino = INO64TO32(bdp->d_ino);
479 linux_dirent.d_off = (cookiep)
481 : (l_off_t)(off + reclen);
482 linux_dirent.d_reclen = (l_ushort)linuxreclen;
483 strcpy(linux_dirent.d_name, bdp->d_name);
484 error = copyout(&linux_dirent, outp,
501 resid -= linuxreclen;
507 if (outp == (caddr_t)args->dirent && eofflag == 0)
512 nbytes = resid + linuxreclen;
515 args->sysmsg_iresult = (int)(nbytes - resid);
519 kfree(cookies, M_TEMP);
532 sys_linux_getdents(struct linux_getdents_args *args)
535 if (ldebug(getdents))
536 kprintf(ARGS(getdents, "%d, *, %d"), args->fd, args->count);
538 return (getdents_common((struct linux_getdents64_args*)args, 0));
545 sys_linux_getdents64(struct linux_getdents64_args *args)
548 if (ldebug(getdents64))
549 kprintf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count);
551 return (getdents_common(args, 1));
555 * These exist mainly for hooks for doing /compat/linux translation.
560 sys_linux_access(struct linux_access_args *args)
562 struct nlookupdata nd;
566 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
571 kprintf(ARGS(access, "%s, %d"), path, args->flags);
574 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
576 error = kern_access(&nd, args->flags, 0);
579 linux_free_path(&path);
587 sys_linux_unlink(struct linux_unlink_args *args)
589 struct nlookupdata nd;
593 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
598 kprintf(ARGS(unlink, "%s"), path);
601 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
603 error = kern_unlink(&nd);
606 linux_free_path(&path);
611 sys_linux_unlinkat(struct linux_unlinkat_args *args)
613 struct nlookupdata nd;
618 if (args->flag & ~LINUX_AT_REMOVEDIR)
621 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
623 kprintf("linux_copyin_path says error = %d\n", error);
628 kprintf(ARGS(unlink, "%s"), path);
631 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
633 error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
635 if (args->flag & LINUX_AT_REMOVEDIR)
636 error = kern_rmdir(&nd);
638 error = kern_unlink(&nd);
640 nlookup_done_at(&nd, fp);
642 linux_free_path(&path);
650 sys_linux_chdir(struct linux_chdir_args *args)
652 struct nlookupdata nd;
656 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
661 kprintf(ARGS(chdir, "%s"), path);
664 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
666 error = kern_chdir(&nd);
670 linux_free_path(&path);
678 sys_linux_chmod(struct linux_chmod_args *args)
680 struct nlookupdata nd;
684 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
689 kprintf(ARGS(chmod, "%s, %d"), path, args->mode);
692 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
694 error = kern_chmod(&nd, args->mode);
697 linux_free_path(&path);
705 sys_linux_mkdir(struct linux_mkdir_args *args)
707 struct nlookupdata nd;
711 error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
716 kprintf(ARGS(mkdir, "%s, %d"), path, args->mode);
719 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
721 error = kern_mkdir(&nd, args->mode);
725 linux_free_path(&path);
730 sys_linux_mkdirat(struct linux_mkdirat_args *args)
732 struct nlookupdata nd;
737 error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
742 kprintf(ARGS(mkdir, "%s, %d"), path, args->mode);
744 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
746 error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
748 error = kern_mkdir(&nd, args->mode);
749 nlookup_done_at(&nd, fp);
752 linux_free_path(&path);
760 sys_linux_rmdir(struct linux_rmdir_args *args)
762 struct nlookupdata nd;
766 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
771 kprintf(ARGS(rmdir, "%s"), path);
774 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
776 error = kern_rmdir(&nd);
779 linux_free_path(&path);
787 sys_linux_rename(struct linux_rename_args *args)
789 struct nlookupdata fromnd, tond;
793 error = linux_copyin_path(args->from, &from, LINUX_PATH_EXISTS);
796 error = linux_copyin_path(args->to, &to, LINUX_PATH_CREATE);
798 linux_free_path(&from);
803 kprintf(ARGS(rename, "%s, %s"), from, to);
806 error = nlookup_init(&fromnd, from, UIO_SYSSPACE, 0);
808 error = nlookup_init(&tond, to, UIO_SYSSPACE, 0);
810 error = kern_rename(&fromnd, &tond);
813 nlookup_done(&fromnd);
815 linux_free_path(&from);
816 linux_free_path(&to);
821 sys_linux_renameat(struct linux_renameat_args *args)
823 struct nlookupdata fromnd, tond;
824 struct file *fp, *fp2;
826 int olddfd, newdfd,error;
828 error = linux_copyin_path(args->from, &from, LINUX_PATH_EXISTS);
831 error = linux_copyin_path(args->to, &to, LINUX_PATH_CREATE);
833 linux_free_path(&from);
838 kprintf(ARGS(rename, "%s, %s"), from, to);
840 olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
841 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
843 error = nlookup_init_at(&fromnd, &fp, olddfd, from, UIO_SYSSPACE, 0);
845 error = nlookup_init_at(&tond, &fp2, newdfd, to, UIO_SYSSPACE, 0);
847 error = kern_rename(&fromnd, &tond);
848 nlookup_done_at(&tond, fp2);
850 nlookup_done_at(&fromnd, fp);
852 linux_free_path(&from);
853 linux_free_path(&to);
861 sys_linux_symlink(struct linux_symlink_args *args)
863 struct thread *td = curthread;
864 struct nlookupdata nd;
869 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
872 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
874 linux_free_path(&path);
879 kprintf(ARGS(symlink, "%s, %s"), path, link);
882 error = nlookup_init(&nd, link, UIO_SYSSPACE, 0);
884 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
885 error = kern_symlink(&nd, path, mode);
889 linux_free_path(&path);
890 linux_free_path(&link);
895 sys_linux_symlinkat(struct linux_symlinkat_args *args)
897 struct thread *td = curthread;
898 struct nlookupdata nd;
904 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
907 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
909 linux_free_path(&path);
914 kprintf(ARGS(symlink, "%s, %s"), path, link);
916 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
918 error = nlookup_init_at(&nd, &fp, newdfd, link, UIO_SYSSPACE, 0);
920 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
921 error = kern_symlink(&nd, path, mode);
923 nlookup_done_at(&nd, fp);
925 linux_free_path(&path);
926 linux_free_path(&link);
934 sys_linux_readlink(struct linux_readlink_args *args)
936 struct nlookupdata nd;
940 error = linux_copyin_path(args->name, &path, LINUX_PATH_EXISTS);
944 if (ldebug(readlink))
945 kprintf(ARGS(readlink, "%s, %p, %d"), path, (void *)args->buf,
949 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
951 error = kern_readlink(&nd, args->buf, args->count,
952 &args->sysmsg_iresult);
956 linux_free_path(&path);
961 sys_linux_readlinkat(struct linux_readlinkat_args *args)
963 struct nlookupdata nd;
968 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
972 if (ldebug(readlink))
973 kprintf(ARGS(readlink, "%s, %p, %d"), path, (void *)args->buf,
976 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
978 error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
980 error = kern_readlink(&nd, args->buf, args->count,
981 &args->sysmsg_iresult);
983 nlookup_done_at(&nd, fp);
985 linux_free_path(&path);
993 sys_linux_truncate(struct linux_truncate_args *args)
995 struct nlookupdata nd;
999 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1003 if (ldebug(truncate))
1004 kprintf(ARGS(truncate, "%s, %ld"), path,
1005 (long)args->length);
1008 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1010 error = kern_truncate(&nd, args->length);
1013 linux_free_path(&path);
1021 sys_linux_truncate64(struct linux_truncate64_args *args)
1023 struct nlookupdata nd;
1027 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1031 if (ldebug(truncate64))
1032 kprintf(ARGS(truncate64, "%s, %lld"), path,
1033 (off_t)args->length);
1036 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1038 error = kern_truncate(&nd, args->length);
1041 linux_free_path(&path);
1049 sys_linux_ftruncate(struct linux_ftruncate_args *args)
1054 if (ldebug(ftruncate))
1055 kprintf(ARGS(ftruncate, "%d, %ld"), args->fd,
1056 (long)args->length);
1059 error = kern_ftruncate(args->fd, args->length);
1069 sys_linux_ftruncate64(struct linux_ftruncate64_args *args)
1074 if (ldebug(ftruncate))
1075 kprintf(ARGS(ftruncate64, "%d, %lld"), args->fd,
1076 (off_t)args->length);
1079 error = kern_ftruncate(args->fd, args->length);
1089 sys_linux_link(struct linux_link_args *args)
1091 struct nlookupdata nd, linknd;
1095 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1098 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
1100 linux_free_path(&path);
1105 kprintf(ARGS(link, "%s, %s"), path, link);
1108 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1110 error = nlookup_init(&linknd, link, UIO_SYSSPACE, 0);
1112 error = kern_link(&nd, &linknd);
1113 nlookup_done(&linknd);
1117 linux_free_path(&path);
1118 linux_free_path(&link);
1123 sys_linux_linkat(struct linux_linkat_args *args)
1125 struct nlookupdata nd, linknd;
1126 struct file *fp, *fp2;
1128 int olddfd, newdfd, error;
1130 if (args->flags != 0)
1133 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1136 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
1138 linux_free_path(&path);
1143 kprintf(ARGS(link, "%s, %s"), path, link);
1145 olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
1146 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
1148 error = nlookup_init_at(&nd, &fp, olddfd, path, UIO_SYSSPACE, NLC_FOLLOW);
1150 error = nlookup_init_at(&linknd, &fp2, newdfd, link, UIO_SYSSPACE, 0);
1152 error = kern_link(&nd, &linknd);
1153 nlookup_done_at(&linknd, fp2);
1155 nlookup_done_at(&nd, fp);
1157 linux_free_path(&path);
1158 linux_free_path(&link);
1166 sys_linux_fdatasync(struct linux_fdatasync_args *uap)
1168 struct fsync_args bsd;
1172 bsd.sysmsg_iresult = 0;
1174 error = sys_fsync(&bsd);
1175 uap->sysmsg_iresult = bsd.sysmsg_iresult;
1183 sys_linux_pread(struct linux_pread_args *uap)
1185 struct thread *td = curthread;
1190 aiov.iov_base = uap->buf;
1191 aiov.iov_len = uap->nbyte;
1192 auio.uio_iov = &aiov;
1193 auio.uio_iovcnt = 1;
1194 auio.uio_offset = uap->offset;
1195 auio.uio_resid = uap->nbyte;
1196 auio.uio_rw = UIO_READ;
1197 auio.uio_segflg = UIO_USERSPACE;
1200 if ((ssize_t)auio.uio_resid < 0) {
1203 error = kern_preadv(uap->fd, &auio, O_FOFFSET,
1204 &uap->sysmsg_szresult);
1213 sys_linux_pwrite(struct linux_pwrite_args *uap)
1215 struct thread *td = curthread;
1220 aiov.iov_base = uap->buf;
1221 aiov.iov_len = uap->nbyte;
1222 auio.uio_iov = &aiov;
1223 auio.uio_iovcnt = 1;
1224 auio.uio_offset = uap->offset;
1225 auio.uio_resid = uap->nbyte;
1226 auio.uio_rw = UIO_WRITE;
1227 auio.uio_segflg = UIO_USERSPACE;
1230 if ((ssize_t)auio.uio_resid < 0) {
1233 error = kern_pwritev(uap->fd, &auio, O_FOFFSET,
1234 &uap->sysmsg_szresult);
1243 sys_linux_oldumount(struct linux_oldumount_args *args)
1245 struct linux_umount_args args2;
1248 args2.path = args->path;
1250 args2.sysmsg_iresult = 0;
1251 error = sys_linux_umount(&args2);
1252 args->sysmsg_iresult = args2.sysmsg_iresult;
1260 sys_linux_umount(struct linux_umount_args *args)
1262 struct unmount_args bsd;
1265 bsd.path = args->path;
1266 bsd.flags = args->flags; /* XXX correct? */
1267 bsd.sysmsg_iresult = 0;
1269 error = sys_unmount(&bsd);
1270 args->sysmsg_iresult = bsd.sysmsg_iresult;
1275 * fcntl family of syscalls
1289 linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
1291 switch (linux_flock->l_type) {
1293 bsd_flock->l_type = F_RDLCK;
1296 bsd_flock->l_type = F_WRLCK;
1299 bsd_flock->l_type = F_UNLCK;
1302 bsd_flock->l_type = -1;
1305 bsd_flock->l_whence = linux_flock->l_whence;
1306 bsd_flock->l_start = (off_t)linux_flock->l_start;
1307 bsd_flock->l_len = (off_t)linux_flock->l_len;
1308 bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1315 bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
1317 switch (bsd_flock->l_type) {
1319 linux_flock->l_type = LINUX_F_RDLCK;
1322 linux_flock->l_type = LINUX_F_WRLCK;
1325 linux_flock->l_type = LINUX_F_UNLCK;
1328 linux_flock->l_whence = bsd_flock->l_whence;
1329 linux_flock->l_start = (l_off_t)bsd_flock->l_start;
1330 linux_flock->l_len = (l_off_t)bsd_flock->l_len;
1331 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
1334 #if defined(__i386__)
1347 linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
1349 switch (linux_flock->l_type) {
1351 bsd_flock->l_type = F_RDLCK;
1354 bsd_flock->l_type = F_WRLCK;
1357 bsd_flock->l_type = F_UNLCK;
1360 bsd_flock->l_type = -1;
1363 bsd_flock->l_whence = linux_flock->l_whence;
1364 bsd_flock->l_start = (off_t)linux_flock->l_start;
1365 bsd_flock->l_len = (off_t)linux_flock->l_len;
1366 bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1373 bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
1375 switch (bsd_flock->l_type) {
1377 linux_flock->l_type = LINUX_F_RDLCK;
1380 linux_flock->l_type = LINUX_F_WRLCK;
1383 linux_flock->l_type = LINUX_F_UNLCK;
1386 linux_flock->l_whence = bsd_flock->l_whence;
1387 linux_flock->l_start = (l_loff_t)bsd_flock->l_start;
1388 linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
1389 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
1391 #endif /* __i386__ */
1397 linux_fcntl_common(struct linux_fcntl64_args *args)
1399 struct thread *td = curthread;
1400 struct l_flock linux_flock;
1402 union fcntl_dat dat;
1405 switch (args->cmd) {
1408 dat.fc_fd = args->arg;
1415 dat.fc_cloexec = args->arg;
1423 if (args->arg & LINUX_O_NDELAY)
1424 dat.fc_flags |= O_NONBLOCK;
1425 if (args->arg & LINUX_O_APPEND)
1426 dat.fc_flags |= O_APPEND;
1427 if (args->arg & LINUX_O_SYNC)
1428 dat.fc_flags |= O_FSYNC;
1429 if (args->arg & LINUX_FASYNC)
1430 dat.fc_flags |= O_ASYNC;
1434 case LINUX_F_SETLKW:
1436 error = copyin((caddr_t)args->arg, &linux_flock,
1437 sizeof(linux_flock));
1440 linux_to_bsd_flock(&linux_flock, &dat.fc_flock);
1442 case LINUX_F_GETOWN:
1445 case LINUX_F_SETOWN:
1447 * XXX some Linux applications depend on F_SETOWN having no
1448 * significant effect for pipes (SIGIO is not delivered for
1449 * pipes under Linux-2.2.35 at least).
1451 fp = holdfp(td->td_proc->p_fd, args->fd, -1);
1454 if (fp->f_type == DTYPE_PIPE) {
1460 dat.fc_owner = args->arg;
1467 error = kern_fcntl(args->fd, cmd, &dat, td->td_ucred);
1470 switch (args->cmd) {
1472 args->sysmsg_iresult = dat.fc_fd;
1475 args->sysmsg_iresult = dat.fc_cloexec;
1480 args->sysmsg_iresult = 0;
1481 if (dat.fc_flags & O_RDONLY)
1482 args->sysmsg_iresult |= LINUX_O_RDONLY;
1483 if (dat.fc_flags & O_WRONLY)
1484 args->sysmsg_iresult |= LINUX_O_WRONLY;
1485 if (dat.fc_flags & O_RDWR)
1486 args->sysmsg_iresult |= LINUX_O_RDWR;
1487 if (dat.fc_flags & O_NDELAY)
1488 args->sysmsg_iresult |= LINUX_O_NONBLOCK;
1489 if (dat.fc_flags & O_APPEND)
1490 args->sysmsg_iresult |= LINUX_O_APPEND;
1491 if (dat.fc_flags & O_FSYNC)
1492 args->sysmsg_iresult |= LINUX_O_SYNC;
1493 if (dat.fc_flags & O_ASYNC)
1494 args->sysmsg_iresult |= LINUX_FASYNC;
1497 bsd_to_linux_flock(&dat.fc_flock, &linux_flock);
1498 error = copyout(&linux_flock, (caddr_t)args->arg,
1499 sizeof(linux_flock));
1502 case LINUX_F_SETLKW:
1504 case LINUX_F_GETOWN:
1505 args->sysmsg_iresult = dat.fc_owner;
1507 case LINUX_F_SETOWN:
1519 sys_linux_fcntl(struct linux_fcntl_args *args)
1521 struct linux_fcntl64_args args64;
1526 kprintf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
1529 args64.fd = args->fd;
1530 args64.cmd = args->cmd;
1531 args64.arg = args->arg;
1532 args64.sysmsg_iresult = 0;
1533 error = linux_fcntl_common(&args64);
1534 args->sysmsg_iresult = args64.sysmsg_iresult;
1538 #if defined(__i386__)
1543 sys_linux_fcntl64(struct linux_fcntl64_args *args)
1545 struct thread *td = curthread;
1546 struct l_flock64 linux_flock;
1547 union fcntl_dat dat;
1551 if (ldebug(fcntl64))
1552 kprintf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd);
1554 if (args->cmd == LINUX_F_GETLK64 || args->cmd == LINUX_F_SETLK64 ||
1555 args->cmd == LINUX_F_SETLKW64) {
1556 switch (args->cmd) {
1557 case LINUX_F_GETLK64:
1560 case LINUX_F_SETLK64:
1563 case LINUX_F_SETLKW64:
1568 error = copyin((caddr_t)args->arg, &linux_flock,
1569 sizeof(linux_flock));
1572 linux_to_bsd_flock64(&linux_flock, &dat.fc_flock);
1575 error = kern_fcntl(args->fd, cmd, &dat, td->td_ucred);
1577 if (error == 0 && args->cmd == LINUX_F_GETLK64) {
1578 bsd_to_linux_flock64(&dat.fc_flock, &linux_flock);
1579 error = copyout(&linux_flock, (caddr_t)args->arg,
1580 sizeof(linux_flock));
1583 error = linux_fcntl_common(args);
1588 #endif /* __i386__ */
1594 sys_linux_chown(struct linux_chown_args *args)
1596 struct nlookupdata nd;
1600 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1605 kprintf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid);
1608 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1610 error = kern_chown(&nd, args->uid, args->gid);
1613 linux_free_path(&path);
1621 sys_linux_lchown(struct linux_lchown_args *args)
1623 struct nlookupdata nd;
1627 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1632 kprintf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid);
1635 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
1637 error = kern_chown(&nd, args->uid, args->gid);
1640 linux_free_path(&path);
1645 sys_linux_fchmodat(struct linux_fchmodat_args *args)
1647 struct fchmodat_args uap;
1650 uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1651 uap.path = args->filename;
1652 uap.mode = args->mode;
1655 error = sys_fchmodat(&uap);
1661 sys_linux_fchownat(struct linux_fchownat_args *args)
1663 struct fchownat_args uap;
1666 if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
1669 uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1670 uap.path = args->filename;
1671 uap.uid = args->uid;
1672 uap.gid = args->gid;
1673 uap.flags = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 :
1674 AT_SYMLINK_NOFOLLOW;
1676 error = sys_fchownat(&uap);
1682 sys_linux_faccessat(struct linux_faccessat_args *args)
1684 struct faccessat_args uap;
1687 uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1688 uap.path = args->filename;
1689 uap.amode = args->mode;
1692 error = sys_faccessat(&uap);