xref: /freebsd/sys/compat/linux/linux_file.c (revision 47dd1d1b619cc035b82b49a91a25544309ff95ae)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1994-1995 Søren Schmidt
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include "opt_compat.h"
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/capsicum.h>
37 #include <sys/conf.h>
38 #include <sys/dirent.h>
39 #include <sys/fcntl.h>
40 #include <sys/file.h>
41 #include <sys/filedesc.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/mount.h>
45 #include <sys/mutex.h>
46 #include <sys/namei.h>
47 #include <sys/proc.h>
48 #include <sys/stat.h>
49 #include <sys/sx.h>
50 #include <sys/syscallsubr.h>
51 #include <sys/sysproto.h>
52 #include <sys/tty.h>
53 #include <sys/unistd.h>
54 #include <sys/vnode.h>
55 
56 #ifdef COMPAT_LINUX32
57 #include <machine/../linux32/linux.h>
58 #include <machine/../linux32/linux32_proto.h>
59 #else
60 #include <machine/../linux/linux.h>
61 #include <machine/../linux/linux_proto.h>
62 #endif
63 #include <compat/linux/linux_misc.h>
64 #include <compat/linux/linux_util.h>
65 #include <compat/linux/linux_file.h>
66 
67 static int	linux_common_open(struct thread *, int, char *, int, int);
68 static int	linux_getdents_error(struct thread *, int, int);
69 
70 
71 int
72 linux_creat(struct thread *td, struct linux_creat_args *args)
73 {
74 	char *path;
75 	int error;
76 
77 	LCONVPATHEXIST(td, args->path, &path);
78 #ifdef DEBUG
79 	if (ldebug(creat))
80 		printf(ARGS(creat, "%s, %d"), path, args->mode);
81 #endif
82 	error = kern_openat(td, AT_FDCWD, path, UIO_SYSSPACE,
83 	    O_WRONLY | O_CREAT | O_TRUNC, args->mode);
84 	LFREEPATH(path);
85 	return (error);
86 }
87 
88 
89 static int
90 linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mode)
91 {
92 	struct proc *p = td->td_proc;
93 	struct file *fp;
94 	int fd;
95 	int bsd_flags, error;
96 
97 	bsd_flags = 0;
98 	switch (l_flags & LINUX_O_ACCMODE) {
99 	case LINUX_O_WRONLY:
100 		bsd_flags |= O_WRONLY;
101 		break;
102 	case LINUX_O_RDWR:
103 		bsd_flags |= O_RDWR;
104 		break;
105 	default:
106 		bsd_flags |= O_RDONLY;
107 	}
108 	if (l_flags & LINUX_O_NDELAY)
109 		bsd_flags |= O_NONBLOCK;
110 	if (l_flags & LINUX_O_APPEND)
111 		bsd_flags |= O_APPEND;
112 	if (l_flags & LINUX_O_SYNC)
113 		bsd_flags |= O_FSYNC;
114 	if (l_flags & LINUX_O_NONBLOCK)
115 		bsd_flags |= O_NONBLOCK;
116 	if (l_flags & LINUX_FASYNC)
117 		bsd_flags |= O_ASYNC;
118 	if (l_flags & LINUX_O_CREAT)
119 		bsd_flags |= O_CREAT;
120 	if (l_flags & LINUX_O_TRUNC)
121 		bsd_flags |= O_TRUNC;
122 	if (l_flags & LINUX_O_EXCL)
123 		bsd_flags |= O_EXCL;
124 	if (l_flags & LINUX_O_NOCTTY)
125 		bsd_flags |= O_NOCTTY;
126 	if (l_flags & LINUX_O_DIRECT)
127 		bsd_flags |= O_DIRECT;
128 	if (l_flags & LINUX_O_NOFOLLOW)
129 		bsd_flags |= O_NOFOLLOW;
130 	if (l_flags & LINUX_O_DIRECTORY)
131 		bsd_flags |= O_DIRECTORY;
132 	/* XXX LINUX_O_NOATIME: unable to be easily implemented. */
133 
134 	error = kern_openat(td, dirfd, path, UIO_SYSSPACE, bsd_flags, mode);
135 	if (error != 0)
136 		goto done;
137 	if (bsd_flags & O_NOCTTY)
138 		goto done;
139 
140 	/*
141 	 * XXX In between kern_openat() and fget(), another process
142 	 * having the same filedesc could use that fd without
143 	 * checking below.
144 	*/
145 	fd = td->td_retval[0];
146 	if (fget(td, fd, &cap_ioctl_rights, &fp) == 0) {
147 		if (fp->f_type != DTYPE_VNODE) {
148 			fdrop(fp, td);
149 			goto done;
150 		}
151 		sx_slock(&proctree_lock);
152 		PROC_LOCK(p);
153 		if (SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
154 			PROC_UNLOCK(p);
155 			sx_sunlock(&proctree_lock);
156 			/* XXXPJD: Verify if TIOCSCTTY is allowed. */
157 			(void) fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0,
158 			    td->td_ucred, td);
159 		} else {
160 			PROC_UNLOCK(p);
161 			sx_sunlock(&proctree_lock);
162 		}
163 		fdrop(fp, td);
164 	}
165 
166 done:
167 #ifdef DEBUG
168 	if (ldebug(open))
169 		printf(LMSG("open returns error %d"), error);
170 #endif
171 	LFREEPATH(path);
172 	return (error);
173 }
174 
175 int
176 linux_openat(struct thread *td, struct linux_openat_args *args)
177 {
178 	char *path;
179 	int dfd;
180 
181 	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
182 	if (args->flags & LINUX_O_CREAT)
183 		LCONVPATH_AT(td, args->filename, &path, 1, dfd);
184 	else
185 		LCONVPATH_AT(td, args->filename, &path, 0, dfd);
186 #ifdef DEBUG
187 	if (ldebug(openat))
188 		printf(ARGS(openat, "%i, %s, 0x%x, 0x%x"), args->dfd,
189 		    path, args->flags, args->mode);
190 #endif
191 	return (linux_common_open(td, dfd, path, args->flags, args->mode));
192 }
193 
194 int
195 linux_open(struct thread *td, struct linux_open_args *args)
196 {
197 	char *path;
198 
199 	if (args->flags & LINUX_O_CREAT)
200 		LCONVPATHCREAT(td, args->path, &path);
201 	else
202 		LCONVPATHEXIST(td, args->path, &path);
203 #ifdef DEBUG
204 	if (ldebug(open))
205 		printf(ARGS(open, "%s, 0x%x, 0x%x"),
206 		    path, args->flags, args->mode);
207 #endif
208 	return (linux_common_open(td, AT_FDCWD, path, args->flags, args->mode));
209 }
210 
211 int
212 linux_lseek(struct thread *td, struct linux_lseek_args *args)
213 {
214 
215 #ifdef DEBUG
216 	if (ldebug(lseek))
217 		printf(ARGS(lseek, "%d, %ld, %d"),
218 		    args->fdes, (long)args->off, args->whence);
219 #endif
220 	return (kern_lseek(td, args->fdes, args->off, args->whence));
221 }
222 
223 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
224 int
225 linux_llseek(struct thread *td, struct linux_llseek_args *args)
226 {
227 	int error;
228 	off_t off;
229 
230 #ifdef DEBUG
231 	if (ldebug(llseek))
232 		printf(ARGS(llseek, "%d, %d:%d, %d"),
233 		    args->fd, args->ohigh, args->olow, args->whence);
234 #endif
235 	off = (args->olow) | (((off_t) args->ohigh) << 32);
236 
237 	error = kern_lseek(td, args->fd, off, args->whence);
238 	if (error != 0)
239 		return (error);
240 
241 	error = copyout(td->td_retval, args->res, sizeof(off_t));
242 	if (error != 0)
243 		return (error);
244 
245 	td->td_retval[0] = 0;
246 	return (0);
247 }
248 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
249 
250 /*
251  * Note that linux_getdents(2) and linux_getdents64(2) have the same
252  * arguments. They only differ in the definition of struct dirent they
253  * operate on.
254  * Note that linux_readdir(2) is a special case of linux_getdents(2)
255  * where count is always equals 1, meaning that the buffer is one
256  * dirent-structure in size and that the code can't handle more anyway.
257  * Note that linux_readdir(2) can't be implemented by means of linux_getdents(2)
258  * as in case when the *dent buffer size is equal to 1 linux_getdents(2) will
259  * trash user stack.
260  */
261 
262 static int
263 linux_getdents_error(struct thread *td, int fd, int err)
264 {
265 	struct vnode *vp;
266 	struct file *fp;
267 	int error;
268 
269 	/* Linux return ENOTDIR in case when fd is not a directory. */
270 	error = getvnode(td, fd, &cap_read_rights, &fp);
271 	if (error != 0)
272 		return (error);
273 	vp = fp->f_vnode;
274 	if (vp->v_type != VDIR) {
275 		fdrop(fp, td);
276 		return (ENOTDIR);
277 	}
278 	fdrop(fp, td);
279 	return (err);
280 }
281 
282 struct l_dirent {
283 	l_ulong		d_ino;
284 	l_off_t		d_off;
285 	l_ushort	d_reclen;
286 	char		d_name[LINUX_NAME_MAX + 1];
287 };
288 
289 struct l_dirent64 {
290 	uint64_t	d_ino;
291 	int64_t		d_off;
292 	l_ushort	d_reclen;
293 	u_char		d_type;
294 	char		d_name[LINUX_NAME_MAX + 1];
295 };
296 
297 /*
298  * Linux uses the last byte in the dirent buffer to store d_type,
299  * at least glibc-2.7 requires it. That is why l_dirent is padded with 2 bytes.
300  */
301 #define LINUX_RECLEN(namlen)						\
302     roundup(offsetof(struct l_dirent, d_name) + (namlen) + 2, sizeof(l_ulong))
303 
304 #define LINUX_RECLEN64(namlen)						\
305     roundup(offsetof(struct l_dirent64, d_name) + (namlen) + 1,		\
306     sizeof(uint64_t))
307 
308 int
309 linux_getdents(struct thread *td, struct linux_getdents_args *args)
310 {
311 	struct dirent *bdp;
312 	caddr_t inp, buf;		/* BSD-format */
313 	int len, reclen;		/* BSD-format */
314 	caddr_t outp;			/* Linux-format */
315 	int resid, linuxreclen;		/* Linux-format */
316 	caddr_t lbuf;			/* Linux-format */
317 	off_t base;
318 	struct l_dirent *linux_dirent;
319 	int buflen, error;
320 	size_t retval;
321 
322 #ifdef DEBUG
323 	if (ldebug(getdents))
324 		printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count);
325 #endif
326 	buflen = min(args->count, MAXBSIZE);
327 	buf = malloc(buflen, M_TEMP, M_WAITOK);
328 
329 	error = kern_getdirentries(td, args->fd, buf, buflen,
330 	    &base, NULL, UIO_SYSSPACE);
331 	if (error != 0) {
332 		error = linux_getdents_error(td, args->fd, error);
333 		goto out1;
334 	}
335 
336 	lbuf = malloc(LINUX_RECLEN(LINUX_NAME_MAX), M_TEMP, M_WAITOK | M_ZERO);
337 
338 	len = td->td_retval[0];
339 	inp = buf;
340 	outp = (caddr_t)args->dent;
341 	resid = args->count;
342 	retval = 0;
343 
344 	while (len > 0) {
345 		bdp = (struct dirent *) inp;
346 		reclen = bdp->d_reclen;
347 		linuxreclen = LINUX_RECLEN(bdp->d_namlen);
348 		/*
349 		 * No more space in the user supplied dirent buffer.
350 		 * Return EINVAL.
351 		 */
352 		if (resid < linuxreclen) {
353 			error = EINVAL;
354 			goto out;
355 		}
356 
357 		linux_dirent = (struct l_dirent*)lbuf;
358 		linux_dirent->d_ino = bdp->d_fileno;
359 		linux_dirent->d_off = base + reclen;
360 		linux_dirent->d_reclen = linuxreclen;
361 		/*
362 		 * Copy d_type to last byte of l_dirent buffer
363 		 */
364 		lbuf[linuxreclen - 1] = bdp->d_type;
365 		strlcpy(linux_dirent->d_name, bdp->d_name,
366 		    linuxreclen - offsetof(struct l_dirent, d_name)-1);
367 		error = copyout(linux_dirent, outp, linuxreclen);
368 		if (error != 0)
369 			goto out;
370 
371 		inp += reclen;
372 		base += reclen;
373 		len -= reclen;
374 
375 		retval += linuxreclen;
376 		outp += linuxreclen;
377 		resid -= linuxreclen;
378 	}
379 	td->td_retval[0] = retval;
380 
381 out:
382 	free(lbuf, M_TEMP);
383 out1:
384 	free(buf, M_TEMP);
385 	return (error);
386 }
387 
388 int
389 linux_getdents64(struct thread *td, struct linux_getdents64_args *args)
390 {
391 	struct dirent *bdp;
392 	caddr_t inp, buf;		/* BSD-format */
393 	int len, reclen;		/* BSD-format */
394 	caddr_t outp;			/* Linux-format */
395 	int resid, linuxreclen;		/* Linux-format */
396 	caddr_t lbuf;			/* Linux-format */
397 	off_t base;
398 	struct l_dirent64 *linux_dirent64;
399 	int buflen, error;
400 	size_t retval;
401 
402 #ifdef DEBUG
403 	if (ldebug(getdents64))
404 		uprintf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count);
405 #endif
406 	buflen = min(args->count, MAXBSIZE);
407 	buf = malloc(buflen, M_TEMP, M_WAITOK);
408 
409 	error = kern_getdirentries(td, args->fd, buf, buflen,
410 	    &base, NULL, UIO_SYSSPACE);
411 	if (error != 0) {
412 		error = linux_getdents_error(td, args->fd, error);
413 		goto out1;
414 	}
415 
416 	lbuf = malloc(LINUX_RECLEN64(LINUX_NAME_MAX), M_TEMP, M_WAITOK | M_ZERO);
417 
418 	len = td->td_retval[0];
419 	inp = buf;
420 	outp = (caddr_t)args->dirent;
421 	resid = args->count;
422 	retval = 0;
423 
424 	while (len > 0) {
425 		bdp = (struct dirent *) inp;
426 		reclen = bdp->d_reclen;
427 		linuxreclen = LINUX_RECLEN64(bdp->d_namlen);
428 		/*
429 		 * No more space in the user supplied dirent buffer.
430 		 * Return EINVAL.
431 		 */
432 		if (resid < linuxreclen) {
433 			error = EINVAL;
434 			goto out;
435 		}
436 
437 		linux_dirent64 = (struct l_dirent64*)lbuf;
438 		linux_dirent64->d_ino = bdp->d_fileno;
439 		linux_dirent64->d_off = base + reclen;
440 		linux_dirent64->d_reclen = linuxreclen;
441 		linux_dirent64->d_type = bdp->d_type;
442 		strlcpy(linux_dirent64->d_name, bdp->d_name,
443 		    linuxreclen - offsetof(struct l_dirent64, d_name));
444 		error = copyout(linux_dirent64, outp, linuxreclen);
445 		if (error != 0)
446 			goto out;
447 
448 		inp += reclen;
449 		base += reclen;
450 		len -= reclen;
451 
452 		retval += linuxreclen;
453 		outp += linuxreclen;
454 		resid -= linuxreclen;
455 	}
456 	td->td_retval[0] = retval;
457 
458 out:
459 	free(lbuf, M_TEMP);
460 out1:
461 	free(buf, M_TEMP);
462 	return (error);
463 }
464 
465 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
466 int
467 linux_readdir(struct thread *td, struct linux_readdir_args *args)
468 {
469 	struct dirent *bdp;
470 	caddr_t buf;			/* BSD-format */
471 	int linuxreclen;		/* Linux-format */
472 	caddr_t lbuf;			/* Linux-format */
473 	off_t base;
474 	struct l_dirent *linux_dirent;
475 	int buflen, error;
476 
477 #ifdef DEBUG
478 	if (ldebug(readdir))
479 		printf(ARGS(readdir, "%d, *"), args->fd);
480 #endif
481 	buflen = LINUX_RECLEN(LINUX_NAME_MAX);
482 	buf = malloc(buflen, M_TEMP, M_WAITOK);
483 
484 	error = kern_getdirentries(td, args->fd, buf, buflen,
485 	    &base, NULL, UIO_SYSSPACE);
486 	if (error != 0) {
487 		error = linux_getdents_error(td, args->fd, error);
488 		goto out;
489 	}
490 	if (td->td_retval[0] == 0)
491 		goto out;
492 
493 	lbuf = malloc(LINUX_RECLEN(LINUX_NAME_MAX), M_TEMP, M_WAITOK | M_ZERO);
494 
495 	bdp = (struct dirent *) buf;
496 	linuxreclen = LINUX_RECLEN(bdp->d_namlen);
497 
498 	linux_dirent = (struct l_dirent*)lbuf;
499 	linux_dirent->d_ino = bdp->d_fileno;
500 	linux_dirent->d_off = linuxreclen;
501 	linux_dirent->d_reclen = bdp->d_namlen;
502 	strlcpy(linux_dirent->d_name, bdp->d_name,
503 	    linuxreclen - offsetof(struct l_dirent, d_name));
504 	error = copyout(linux_dirent, args->dent, linuxreclen);
505 	if (error == 0)
506 		td->td_retval[0] = linuxreclen;
507 
508 	free(lbuf, M_TEMP);
509 out:
510 	free(buf, M_TEMP);
511 	return (error);
512 }
513 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
514 
515 
516 /*
517  * These exist mainly for hooks for doing /compat/linux translation.
518  */
519 
520 int
521 linux_access(struct thread *td, struct linux_access_args *args)
522 {
523 	char *path;
524 	int error;
525 
526 	/* Linux convention. */
527 	if (args->amode & ~(F_OK | X_OK | W_OK | R_OK))
528 		return (EINVAL);
529 
530 	LCONVPATHEXIST(td, args->path, &path);
531 
532 #ifdef DEBUG
533 	if (ldebug(access))
534 		printf(ARGS(access, "%s, %d"), path, args->amode);
535 #endif
536 	error = kern_accessat(td, AT_FDCWD, path, UIO_SYSSPACE, 0,
537 	    args->amode);
538 	LFREEPATH(path);
539 
540 	return (error);
541 }
542 
543 int
544 linux_faccessat(struct thread *td, struct linux_faccessat_args *args)
545 {
546 	char *path;
547 	int error, dfd;
548 
549 	/* Linux convention. */
550 	if (args->amode & ~(F_OK | X_OK | W_OK | R_OK))
551 		return (EINVAL);
552 
553 	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
554 	LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
555 
556 #ifdef DEBUG
557 	if (ldebug(access))
558 		printf(ARGS(access, "%s, %d"), path, args->amode);
559 #endif
560 
561 	error = kern_accessat(td, dfd, path, UIO_SYSSPACE, 0, args->amode);
562 	LFREEPATH(path);
563 
564 	return (error);
565 }
566 
567 int
568 linux_unlink(struct thread *td, struct linux_unlink_args *args)
569 {
570 	char *path;
571 	int error;
572 	struct stat st;
573 
574 	LCONVPATHEXIST(td, args->path, &path);
575 
576 #ifdef DEBUG
577 	if (ldebug(unlink))
578 		printf(ARGS(unlink, "%s"), path);
579 #endif
580 
581 	error = kern_unlinkat(td, AT_FDCWD, path, UIO_SYSSPACE, 0);
582 	if (error == EPERM) {
583 		/* Introduce POSIX noncompliant behaviour of Linux */
584 		if (kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st,
585 		    NULL) == 0) {
586 			if (S_ISDIR(st.st_mode))
587 				error = EISDIR;
588 		}
589 	}
590 	LFREEPATH(path);
591 	return (error);
592 }
593 
594 int
595 linux_unlinkat(struct thread *td, struct linux_unlinkat_args *args)
596 {
597 	char *path;
598 	int error, dfd;
599 	struct stat st;
600 
601 	if (args->flag & ~LINUX_AT_REMOVEDIR)
602 		return (EINVAL);
603 
604 	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
605 	LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
606 
607 #ifdef DEBUG
608 	if (ldebug(unlinkat))
609 		printf(ARGS(unlinkat, "%s"), path);
610 #endif
611 
612 	if (args->flag & LINUX_AT_REMOVEDIR)
613 		error = kern_rmdirat(td, dfd, path, UIO_SYSSPACE);
614 	else
615 		error = kern_unlinkat(td, dfd, path, UIO_SYSSPACE, 0);
616 	if (error == EPERM && !(args->flag & LINUX_AT_REMOVEDIR)) {
617 		/* Introduce POSIX noncompliant behaviour of Linux */
618 		if (kern_statat(td, AT_SYMLINK_NOFOLLOW, dfd, path,
619 		    UIO_SYSSPACE, &st, NULL) == 0 && S_ISDIR(st.st_mode))
620 			error = EISDIR;
621 	}
622 	LFREEPATH(path);
623 	return (error);
624 }
625 int
626 linux_chdir(struct thread *td, struct linux_chdir_args *args)
627 {
628 	char *path;
629 	int error;
630 
631 	LCONVPATHEXIST(td, args->path, &path);
632 
633 #ifdef DEBUG
634 	if (ldebug(chdir))
635 		printf(ARGS(chdir, "%s"), path);
636 #endif
637 	error = kern_chdir(td, path, UIO_SYSSPACE);
638 	LFREEPATH(path);
639 	return (error);
640 }
641 
642 int
643 linux_chmod(struct thread *td, struct linux_chmod_args *args)
644 {
645 	char *path;
646 	int error;
647 
648 	LCONVPATHEXIST(td, args->path, &path);
649 
650 #ifdef DEBUG
651 	if (ldebug(chmod))
652 		printf(ARGS(chmod, "%s, %d"), path, args->mode);
653 #endif
654 	error = kern_fchmodat(td, AT_FDCWD, path, UIO_SYSSPACE,
655 	    args->mode, 0);
656 	LFREEPATH(path);
657 	return (error);
658 }
659 
660 int
661 linux_fchmodat(struct thread *td, struct linux_fchmodat_args *args)
662 {
663 	char *path;
664 	int error, dfd;
665 
666 	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
667 	LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
668 
669 #ifdef DEBUG
670 	if (ldebug(fchmodat))
671 		printf(ARGS(fchmodat, "%s, %d"), path, args->mode);
672 #endif
673 
674 	error = kern_fchmodat(td, dfd, path, UIO_SYSSPACE, args->mode, 0);
675 	LFREEPATH(path);
676 	return (error);
677 }
678 
679 int
680 linux_mkdir(struct thread *td, struct linux_mkdir_args *args)
681 {
682 	char *path;
683 	int error;
684 
685 	LCONVPATHCREAT(td, args->path, &path);
686 
687 #ifdef DEBUG
688 	if (ldebug(mkdir))
689 		printf(ARGS(mkdir, "%s, %d"), path, args->mode);
690 #endif
691 	error = kern_mkdirat(td, AT_FDCWD, path, UIO_SYSSPACE, args->mode);
692 	LFREEPATH(path);
693 	return (error);
694 }
695 
696 int
697 linux_mkdirat(struct thread *td, struct linux_mkdirat_args *args)
698 {
699 	char *path;
700 	int error, dfd;
701 
702 	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
703 	LCONVPATHCREAT_AT(td, args->pathname, &path, dfd);
704 
705 #ifdef DEBUG
706 	if (ldebug(mkdirat))
707 		printf(ARGS(mkdirat, "%s, %d"), path, args->mode);
708 #endif
709 	error = kern_mkdirat(td, dfd, path, UIO_SYSSPACE, args->mode);
710 	LFREEPATH(path);
711 	return (error);
712 }
713 
714 int
715 linux_rmdir(struct thread *td, struct linux_rmdir_args *args)
716 {
717 	char *path;
718 	int error;
719 
720 	LCONVPATHEXIST(td, args->path, &path);
721 
722 #ifdef DEBUG
723 	if (ldebug(rmdir))
724 		printf(ARGS(rmdir, "%s"), path);
725 #endif
726 	error = kern_rmdirat(td, AT_FDCWD, path, UIO_SYSSPACE);
727 	LFREEPATH(path);
728 	return (error);
729 }
730 
731 int
732 linux_rename(struct thread *td, struct linux_rename_args *args)
733 {
734 	char *from, *to;
735 	int error;
736 
737 	LCONVPATHEXIST(td, args->from, &from);
738 	/* Expand LCONVPATHCREATE so that `from' can be freed on errors */
739 	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
740 	if (to == NULL) {
741 		LFREEPATH(from);
742 		return (error);
743 	}
744 
745 #ifdef DEBUG
746 	if (ldebug(rename))
747 		printf(ARGS(rename, "%s, %s"), from, to);
748 #endif
749 	error = kern_renameat(td, AT_FDCWD, from, AT_FDCWD, to, UIO_SYSSPACE);
750 	LFREEPATH(from);
751 	LFREEPATH(to);
752 	return (error);
753 }
754 
755 int
756 linux_renameat(struct thread *td, struct linux_renameat_args *args)
757 {
758 	char *from, *to;
759 	int error, olddfd, newdfd;
760 
761 	olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
762 	newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
763 	LCONVPATHEXIST_AT(td, args->oldname, &from, olddfd);
764 	/* Expand LCONVPATHCREATE so that `from' can be freed on errors */
765 	error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd);
766 	if (to == NULL) {
767 		LFREEPATH(from);
768 		return (error);
769 	}
770 
771 #ifdef DEBUG
772 	if (ldebug(renameat))
773 		printf(ARGS(renameat, "%s, %s"), from, to);
774 #endif
775 	error = kern_renameat(td, olddfd, from, newdfd, to, UIO_SYSSPACE);
776 	LFREEPATH(from);
777 	LFREEPATH(to);
778 	return (error);
779 }
780 
781 int
782 linux_symlink(struct thread *td, struct linux_symlink_args *args)
783 {
784 	char *path, *to;
785 	int error;
786 
787 	LCONVPATHEXIST(td, args->path, &path);
788 	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
789 	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
790 	if (to == NULL) {
791 		LFREEPATH(path);
792 		return (error);
793 	}
794 
795 #ifdef DEBUG
796 	if (ldebug(symlink))
797 		printf(ARGS(symlink, "%s, %s"), path, to);
798 #endif
799 	error = kern_symlinkat(td, path, AT_FDCWD, to, UIO_SYSSPACE);
800 	LFREEPATH(path);
801 	LFREEPATH(to);
802 	return (error);
803 }
804 
805 int
806 linux_symlinkat(struct thread *td, struct linux_symlinkat_args *args)
807 {
808 	char *path, *to;
809 	int error, dfd;
810 
811 	dfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
812 	LCONVPATHEXIST(td, args->oldname, &path);
813 	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
814 	error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, dfd);
815 	if (to == NULL) {
816 		LFREEPATH(path);
817 		return (error);
818 	}
819 
820 #ifdef DEBUG
821 	if (ldebug(symlinkat))
822 		printf(ARGS(symlinkat, "%s, %s"), path, to);
823 #endif
824 
825 	error = kern_symlinkat(td, path, dfd, to, UIO_SYSSPACE);
826 	LFREEPATH(path);
827 	LFREEPATH(to);
828 	return (error);
829 }
830 
831 int
832 linux_readlink(struct thread *td, struct linux_readlink_args *args)
833 {
834 	char *name;
835 	int error;
836 
837 	LCONVPATHEXIST(td, args->name, &name);
838 
839 #ifdef DEBUG
840 	if (ldebug(readlink))
841 		printf(ARGS(readlink, "%s, %p, %d"), name, (void *)args->buf,
842 		    args->count);
843 #endif
844 	error = kern_readlinkat(td, AT_FDCWD, name, UIO_SYSSPACE,
845 	    args->buf, UIO_USERSPACE, args->count);
846 	LFREEPATH(name);
847 	return (error);
848 }
849 
850 int
851 linux_readlinkat(struct thread *td, struct linux_readlinkat_args *args)
852 {
853 	char *name;
854 	int error, dfd;
855 
856 	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
857 	LCONVPATHEXIST_AT(td, args->path, &name, dfd);
858 
859 #ifdef DEBUG
860 	if (ldebug(readlinkat))
861 		printf(ARGS(readlinkat, "%s, %p, %d"), name, (void *)args->buf,
862 		    args->bufsiz);
863 #endif
864 
865 	error = kern_readlinkat(td, dfd, name, UIO_SYSSPACE, args->buf,
866 	    UIO_USERSPACE, args->bufsiz);
867 	LFREEPATH(name);
868 	return (error);
869 }
870 
871 int
872 linux_truncate(struct thread *td, struct linux_truncate_args *args)
873 {
874 	char *path;
875 	int error;
876 
877 	LCONVPATHEXIST(td, args->path, &path);
878 
879 #ifdef DEBUG
880 	if (ldebug(truncate))
881 		printf(ARGS(truncate, "%s, %ld"), path, (long)args->length);
882 #endif
883 
884 	error = kern_truncate(td, path, UIO_SYSSPACE, args->length);
885 	LFREEPATH(path);
886 	return (error);
887 }
888 
889 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
890 int
891 linux_truncate64(struct thread *td, struct linux_truncate64_args *args)
892 {
893 	char *path;
894 	int error;
895 
896 	LCONVPATHEXIST(td, args->path, &path);
897 
898 #ifdef DEBUG
899 	if (ldebug(truncate64))
900 		printf(ARGS(truncate64, "%s, %jd"), path, args->length);
901 #endif
902 
903 	error = kern_truncate(td, path, UIO_SYSSPACE, args->length);
904 	LFREEPATH(path);
905 	return (error);
906 }
907 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
908 
909 int
910 linux_ftruncate(struct thread *td, struct linux_ftruncate_args *args)
911 {
912 
913 	return (kern_ftruncate(td, args->fd, args->length));
914 }
915 
916 int
917 linux_link(struct thread *td, struct linux_link_args *args)
918 {
919 	char *path, *to;
920 	int error;
921 
922 	LCONVPATHEXIST(td, args->path, &path);
923 	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
924 	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
925 	if (to == NULL) {
926 		LFREEPATH(path);
927 		return (error);
928 	}
929 
930 #ifdef DEBUG
931 	if (ldebug(link))
932 		printf(ARGS(link, "%s, %s"), path, to);
933 #endif
934 	error = kern_linkat(td, AT_FDCWD, AT_FDCWD, path, to, UIO_SYSSPACE,
935 	    FOLLOW);
936 	LFREEPATH(path);
937 	LFREEPATH(to);
938 	return (error);
939 }
940 
941 int
942 linux_linkat(struct thread *td, struct linux_linkat_args *args)
943 {
944 	char *path, *to;
945 	int error, olddfd, newdfd, follow;
946 
947 	if (args->flag & ~LINUX_AT_SYMLINK_FOLLOW)
948 		return (EINVAL);
949 
950 	olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
951 	newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
952 	LCONVPATHEXIST_AT(td, args->oldname, &path, olddfd);
953 	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
954 	error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd);
955 	if (to == NULL) {
956 		LFREEPATH(path);
957 		return (error);
958 	}
959 
960 #ifdef DEBUG
961 	if (ldebug(linkat))
962 		printf(ARGS(linkat, "%i, %s, %i, %s, %i"), args->olddfd, path,
963 			args->newdfd, to, args->flag);
964 #endif
965 
966 	follow = (args->flag & LINUX_AT_SYMLINK_FOLLOW) == 0 ? NOFOLLOW :
967 	    FOLLOW;
968 	error = kern_linkat(td, olddfd, newdfd, path, to, UIO_SYSSPACE, follow);
969 	LFREEPATH(path);
970 	LFREEPATH(to);
971 	return (error);
972 }
973 
974 int
975 linux_fdatasync(td, uap)
976 	struct thread *td;
977 	struct linux_fdatasync_args *uap;
978 {
979 
980 	return (kern_fsync(td, uap->fd, false));
981 }
982 
983 int
984 linux_pread(struct thread *td, struct linux_pread_args *uap)
985 {
986 	struct vnode *vp;
987 	int error;
988 
989 	error = kern_pread(td, uap->fd, uap->buf, uap->nbyte, uap->offset);
990 	if (error == 0) {
991 		/* This seems to violate POSIX but Linux does it. */
992 		error = fgetvp(td, uap->fd, &cap_pread_rights, &vp);
993 		if (error != 0)
994 			return (error);
995 		if (vp->v_type == VDIR) {
996 			vrele(vp);
997 			return (EISDIR);
998 		}
999 		vrele(vp);
1000 	}
1001 	return (error);
1002 }
1003 
1004 int
1005 linux_pwrite(struct thread *td, struct linux_pwrite_args *uap)
1006 {
1007 
1008 	return (kern_pwrite(td, uap->fd, uap->buf, uap->nbyte, uap->offset));
1009 }
1010 
1011 int
1012 linux_preadv(struct thread *td, struct linux_preadv_args *uap)
1013 {
1014 	struct uio *auio;
1015 	int error;
1016 	off_t offset;
1017 
1018 	/*
1019 	 * According http://man7.org/linux/man-pages/man2/preadv.2.html#NOTES
1020 	 * pos_l and pos_h, respectively, contain the
1021 	 * low order and high order 32 bits of offset.
1022 	 */
1023 	offset = (((off_t)uap->pos_h << (sizeof(offset) * 4)) <<
1024 	    (sizeof(offset) * 4)) | uap->pos_l;
1025 	if (offset < 0)
1026 		return (EINVAL);
1027 #ifdef COMPAT_LINUX32
1028 	error = linux32_copyinuio(PTRIN(uap->vec), uap->vlen, &auio);
1029 #else
1030 	error = copyinuio(uap->vec, uap->vlen, &auio);
1031 #endif
1032 	if (error != 0)
1033 		return (error);
1034 	error = kern_preadv(td, uap->fd, auio, offset);
1035 	free(auio, M_IOV);
1036 	return (error);
1037 }
1038 
1039 int
1040 linux_pwritev(struct thread *td, struct linux_pwritev_args *uap)
1041 {
1042 	struct uio *auio;
1043 	int error;
1044 	off_t offset;
1045 
1046 	/*
1047 	 * According http://man7.org/linux/man-pages/man2/pwritev.2.html#NOTES
1048 	 * pos_l and pos_h, respectively, contain the
1049 	 * low order and high order 32 bits of offset.
1050 	 */
1051 	offset = (((off_t)uap->pos_h << (sizeof(offset) * 4)) <<
1052 	    (sizeof(offset) * 4)) | uap->pos_l;
1053 	if (offset < 0)
1054 		return (EINVAL);
1055 #ifdef COMPAT_LINUX32
1056 	error = linux32_copyinuio(PTRIN(uap->vec), uap->vlen, &auio);
1057 #else
1058 	error = copyinuio(uap->vec, uap->vlen, &auio);
1059 #endif
1060 	if (error != 0)
1061 		return (error);
1062 	error = kern_pwritev(td, uap->fd, auio, offset);
1063 	free(auio, M_IOV);
1064 	return (error);
1065 }
1066 
1067 int
1068 linux_mount(struct thread *td, struct linux_mount_args *args)
1069 {
1070 	char fstypename[MFSNAMELEN];
1071 	char *mntonname, *mntfromname;
1072 	int error, fsflags;
1073 
1074 	mntonname = malloc(MNAMELEN, M_TEMP, M_WAITOK);
1075 	mntfromname = malloc(MNAMELEN, M_TEMP, M_WAITOK);
1076 	error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1,
1077 	    NULL);
1078 	if (error != 0)
1079 		goto out;
1080 	error = copyinstr(args->specialfile, mntfromname, MNAMELEN - 1, NULL);
1081 	if (error != 0)
1082 		goto out;
1083 	error = copyinstr(args->dir, mntonname, MNAMELEN - 1, NULL);
1084 	if (error != 0)
1085 		goto out;
1086 
1087 #ifdef DEBUG
1088 	if (ldebug(mount))
1089 		printf(ARGS(mount, "%s, %s, %s"),
1090 		    fstypename, mntfromname, mntonname);
1091 #endif
1092 
1093 	if (strcmp(fstypename, "ext2") == 0) {
1094 		strcpy(fstypename, "ext2fs");
1095 	} else if (strcmp(fstypename, "proc") == 0) {
1096 		strcpy(fstypename, "linprocfs");
1097 	} else if (strcmp(fstypename, "vfat") == 0) {
1098 		strcpy(fstypename, "msdosfs");
1099 	}
1100 
1101 	fsflags = 0;
1102 
1103 	if ((args->rwflag & 0xffff0000) == 0xc0ed0000) {
1104 		/*
1105 		 * Linux SYNC flag is not included; the closest equivalent
1106 		 * FreeBSD has is !ASYNC, which is our default.
1107 		 */
1108 		if (args->rwflag & LINUX_MS_RDONLY)
1109 			fsflags |= MNT_RDONLY;
1110 		if (args->rwflag & LINUX_MS_NOSUID)
1111 			fsflags |= MNT_NOSUID;
1112 		if (args->rwflag & LINUX_MS_NOEXEC)
1113 			fsflags |= MNT_NOEXEC;
1114 		if (args->rwflag & LINUX_MS_REMOUNT)
1115 			fsflags |= MNT_UPDATE;
1116 	}
1117 
1118 	error = kernel_vmount(fsflags,
1119 	    "fstype", fstypename,
1120 	    "fspath", mntonname,
1121 	    "from", mntfromname,
1122 	    NULL);
1123 out:
1124 	free(mntonname, M_TEMP);
1125 	free(mntfromname, M_TEMP);
1126 	return (error);
1127 }
1128 
1129 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1130 int
1131 linux_oldumount(struct thread *td, struct linux_oldumount_args *args)
1132 {
1133 	struct linux_umount_args args2;
1134 
1135 	args2.path = args->path;
1136 	args2.flags = 0;
1137 	return (linux_umount(td, &args2));
1138 }
1139 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1140 
1141 int
1142 linux_umount(struct thread *td, struct linux_umount_args *args)
1143 {
1144 	struct unmount_args bsd;
1145 
1146 	bsd.path = args->path;
1147 	bsd.flags = args->flags;	/* XXX correct? */
1148 	return (sys_unmount(td, &bsd));
1149 }
1150 
1151 /*
1152  * fcntl family of syscalls
1153  */
1154 
1155 struct l_flock {
1156 	l_short		l_type;
1157 	l_short		l_whence;
1158 	l_off_t		l_start;
1159 	l_off_t		l_len;
1160 	l_pid_t		l_pid;
1161 }
1162 #if defined(__amd64__) && defined(COMPAT_LINUX32)
1163 __packed
1164 #endif
1165 ;
1166 
1167 static void
1168 linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
1169 {
1170 	switch (linux_flock->l_type) {
1171 	case LINUX_F_RDLCK:
1172 		bsd_flock->l_type = F_RDLCK;
1173 		break;
1174 	case LINUX_F_WRLCK:
1175 		bsd_flock->l_type = F_WRLCK;
1176 		break;
1177 	case LINUX_F_UNLCK:
1178 		bsd_flock->l_type = F_UNLCK;
1179 		break;
1180 	default:
1181 		bsd_flock->l_type = -1;
1182 		break;
1183 	}
1184 	bsd_flock->l_whence = linux_flock->l_whence;
1185 	bsd_flock->l_start = (off_t)linux_flock->l_start;
1186 	bsd_flock->l_len = (off_t)linux_flock->l_len;
1187 	bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1188 	bsd_flock->l_sysid = 0;
1189 }
1190 
1191 static void
1192 bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
1193 {
1194 	switch (bsd_flock->l_type) {
1195 	case F_RDLCK:
1196 		linux_flock->l_type = LINUX_F_RDLCK;
1197 		break;
1198 	case F_WRLCK:
1199 		linux_flock->l_type = LINUX_F_WRLCK;
1200 		break;
1201 	case F_UNLCK:
1202 		linux_flock->l_type = LINUX_F_UNLCK;
1203 		break;
1204 	}
1205 	linux_flock->l_whence = bsd_flock->l_whence;
1206 	linux_flock->l_start = (l_off_t)bsd_flock->l_start;
1207 	linux_flock->l_len = (l_off_t)bsd_flock->l_len;
1208 	linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
1209 }
1210 
1211 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1212 struct l_flock64 {
1213 	l_short		l_type;
1214 	l_short		l_whence;
1215 	l_loff_t	l_start;
1216 	l_loff_t	l_len;
1217 	l_pid_t		l_pid;
1218 }
1219 #if defined(__amd64__) && defined(COMPAT_LINUX32)
1220 __packed
1221 #endif
1222 ;
1223 
1224 static void
1225 linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
1226 {
1227 	switch (linux_flock->l_type) {
1228 	case LINUX_F_RDLCK:
1229 		bsd_flock->l_type = F_RDLCK;
1230 		break;
1231 	case LINUX_F_WRLCK:
1232 		bsd_flock->l_type = F_WRLCK;
1233 		break;
1234 	case LINUX_F_UNLCK:
1235 		bsd_flock->l_type = F_UNLCK;
1236 		break;
1237 	default:
1238 		bsd_flock->l_type = -1;
1239 		break;
1240 	}
1241 	bsd_flock->l_whence = linux_flock->l_whence;
1242 	bsd_flock->l_start = (off_t)linux_flock->l_start;
1243 	bsd_flock->l_len = (off_t)linux_flock->l_len;
1244 	bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1245 	bsd_flock->l_sysid = 0;
1246 }
1247 
1248 static void
1249 bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
1250 {
1251 	switch (bsd_flock->l_type) {
1252 	case F_RDLCK:
1253 		linux_flock->l_type = LINUX_F_RDLCK;
1254 		break;
1255 	case F_WRLCK:
1256 		linux_flock->l_type = LINUX_F_WRLCK;
1257 		break;
1258 	case F_UNLCK:
1259 		linux_flock->l_type = LINUX_F_UNLCK;
1260 		break;
1261 	}
1262 	linux_flock->l_whence = bsd_flock->l_whence;
1263 	linux_flock->l_start = (l_loff_t)bsd_flock->l_start;
1264 	linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
1265 	linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
1266 }
1267 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1268 
1269 static int
1270 fcntl_common(struct thread *td, struct linux_fcntl_args *args)
1271 {
1272 	struct l_flock linux_flock;
1273 	struct flock bsd_flock;
1274 	struct file *fp;
1275 	long arg;
1276 	int error, result;
1277 
1278 	switch (args->cmd) {
1279 	case LINUX_F_DUPFD:
1280 		return (kern_fcntl(td, args->fd, F_DUPFD, args->arg));
1281 
1282 	case LINUX_F_GETFD:
1283 		return (kern_fcntl(td, args->fd, F_GETFD, 0));
1284 
1285 	case LINUX_F_SETFD:
1286 		return (kern_fcntl(td, args->fd, F_SETFD, args->arg));
1287 
1288 	case LINUX_F_GETFL:
1289 		error = kern_fcntl(td, args->fd, F_GETFL, 0);
1290 		result = td->td_retval[0];
1291 		td->td_retval[0] = 0;
1292 		if (result & O_RDONLY)
1293 			td->td_retval[0] |= LINUX_O_RDONLY;
1294 		if (result & O_WRONLY)
1295 			td->td_retval[0] |= LINUX_O_WRONLY;
1296 		if (result & O_RDWR)
1297 			td->td_retval[0] |= LINUX_O_RDWR;
1298 		if (result & O_NDELAY)
1299 			td->td_retval[0] |= LINUX_O_NONBLOCK;
1300 		if (result & O_APPEND)
1301 			td->td_retval[0] |= LINUX_O_APPEND;
1302 		if (result & O_FSYNC)
1303 			td->td_retval[0] |= LINUX_O_SYNC;
1304 		if (result & O_ASYNC)
1305 			td->td_retval[0] |= LINUX_FASYNC;
1306 #ifdef LINUX_O_NOFOLLOW
1307 		if (result & O_NOFOLLOW)
1308 			td->td_retval[0] |= LINUX_O_NOFOLLOW;
1309 #endif
1310 #ifdef LINUX_O_DIRECT
1311 		if (result & O_DIRECT)
1312 			td->td_retval[0] |= LINUX_O_DIRECT;
1313 #endif
1314 		return (error);
1315 
1316 	case LINUX_F_SETFL:
1317 		arg = 0;
1318 		if (args->arg & LINUX_O_NDELAY)
1319 			arg |= O_NONBLOCK;
1320 		if (args->arg & LINUX_O_APPEND)
1321 			arg |= O_APPEND;
1322 		if (args->arg & LINUX_O_SYNC)
1323 			arg |= O_FSYNC;
1324 		if (args->arg & LINUX_FASYNC)
1325 			arg |= O_ASYNC;
1326 #ifdef LINUX_O_NOFOLLOW
1327 		if (args->arg & LINUX_O_NOFOLLOW)
1328 			arg |= O_NOFOLLOW;
1329 #endif
1330 #ifdef LINUX_O_DIRECT
1331 		if (args->arg & LINUX_O_DIRECT)
1332 			arg |= O_DIRECT;
1333 #endif
1334 		return (kern_fcntl(td, args->fd, F_SETFL, arg));
1335 
1336 	case LINUX_F_GETLK:
1337 		error = copyin((void *)args->arg, &linux_flock,
1338 		    sizeof(linux_flock));
1339 		if (error)
1340 			return (error);
1341 		linux_to_bsd_flock(&linux_flock, &bsd_flock);
1342 		error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock);
1343 		if (error)
1344 			return (error);
1345 		bsd_to_linux_flock(&bsd_flock, &linux_flock);
1346 		return (copyout(&linux_flock, (void *)args->arg,
1347 		    sizeof(linux_flock)));
1348 
1349 	case LINUX_F_SETLK:
1350 		error = copyin((void *)args->arg, &linux_flock,
1351 		    sizeof(linux_flock));
1352 		if (error)
1353 			return (error);
1354 		linux_to_bsd_flock(&linux_flock, &bsd_flock);
1355 		return (kern_fcntl(td, args->fd, F_SETLK,
1356 		    (intptr_t)&bsd_flock));
1357 
1358 	case LINUX_F_SETLKW:
1359 		error = copyin((void *)args->arg, &linux_flock,
1360 		    sizeof(linux_flock));
1361 		if (error)
1362 			return (error);
1363 		linux_to_bsd_flock(&linux_flock, &bsd_flock);
1364 		return (kern_fcntl(td, args->fd, F_SETLKW,
1365 		     (intptr_t)&bsd_flock));
1366 
1367 	case LINUX_F_GETOWN:
1368 		return (kern_fcntl(td, args->fd, F_GETOWN, 0));
1369 
1370 	case LINUX_F_SETOWN:
1371 		/*
1372 		 * XXX some Linux applications depend on F_SETOWN having no
1373 		 * significant effect for pipes (SIGIO is not delivered for
1374 		 * pipes under Linux-2.2.35 at least).
1375 		 */
1376 		error = fget(td, args->fd,
1377 		    &cap_fcntl_rights, &fp);
1378 		if (error)
1379 			return (error);
1380 		if (fp->f_type == DTYPE_PIPE) {
1381 			fdrop(fp, td);
1382 			return (EINVAL);
1383 		}
1384 		fdrop(fp, td);
1385 
1386 		return (kern_fcntl(td, args->fd, F_SETOWN, args->arg));
1387 
1388 	case LINUX_F_DUPFD_CLOEXEC:
1389 		return (kern_fcntl(td, args->fd, F_DUPFD_CLOEXEC, args->arg));
1390 	}
1391 
1392 	return (EINVAL);
1393 }
1394 
1395 int
1396 linux_fcntl(struct thread *td, struct linux_fcntl_args *args)
1397 {
1398 
1399 #ifdef DEBUG
1400 	if (ldebug(fcntl))
1401 		printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
1402 #endif
1403 
1404 	return (fcntl_common(td, args));
1405 }
1406 
1407 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1408 int
1409 linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args)
1410 {
1411 	struct l_flock64 linux_flock;
1412 	struct flock bsd_flock;
1413 	struct linux_fcntl_args fcntl_args;
1414 	int error;
1415 
1416 #ifdef DEBUG
1417 	if (ldebug(fcntl64))
1418 		printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd);
1419 #endif
1420 
1421 	switch (args->cmd) {
1422 	case LINUX_F_GETLK64:
1423 		error = copyin((void *)args->arg, &linux_flock,
1424 		    sizeof(linux_flock));
1425 		if (error)
1426 			return (error);
1427 		linux_to_bsd_flock64(&linux_flock, &bsd_flock);
1428 		error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock);
1429 		if (error)
1430 			return (error);
1431 		bsd_to_linux_flock64(&bsd_flock, &linux_flock);
1432 		return (copyout(&linux_flock, (void *)args->arg,
1433 			    sizeof(linux_flock)));
1434 
1435 	case LINUX_F_SETLK64:
1436 		error = copyin((void *)args->arg, &linux_flock,
1437 		    sizeof(linux_flock));
1438 		if (error)
1439 			return (error);
1440 		linux_to_bsd_flock64(&linux_flock, &bsd_flock);
1441 		return (kern_fcntl(td, args->fd, F_SETLK,
1442 		    (intptr_t)&bsd_flock));
1443 
1444 	case LINUX_F_SETLKW64:
1445 		error = copyin((void *)args->arg, &linux_flock,
1446 		    sizeof(linux_flock));
1447 		if (error)
1448 			return (error);
1449 		linux_to_bsd_flock64(&linux_flock, &bsd_flock);
1450 		return (kern_fcntl(td, args->fd, F_SETLKW,
1451 		    (intptr_t)&bsd_flock));
1452 	}
1453 
1454 	fcntl_args.fd = args->fd;
1455 	fcntl_args.cmd = args->cmd;
1456 	fcntl_args.arg = args->arg;
1457 	return (fcntl_common(td, &fcntl_args));
1458 }
1459 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1460 
1461 int
1462 linux_chown(struct thread *td, struct linux_chown_args *args)
1463 {
1464 	char *path;
1465 	int error;
1466 
1467 	LCONVPATHEXIST(td, args->path, &path);
1468 
1469 #ifdef DEBUG
1470 	if (ldebug(chown))
1471 		printf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid);
1472 #endif
1473 	error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, args->uid,
1474 	    args->gid, 0);
1475 	LFREEPATH(path);
1476 	return (error);
1477 }
1478 
1479 int
1480 linux_fchownat(struct thread *td, struct linux_fchownat_args *args)
1481 {
1482 	char *path;
1483 	int error, dfd, flag;
1484 
1485 	if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
1486 		return (EINVAL);
1487 
1488 	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD :  args->dfd;
1489 	LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
1490 
1491 #ifdef DEBUG
1492 	if (ldebug(fchownat))
1493 		printf(ARGS(fchownat, "%s, %d, %d"), path, args->uid, args->gid);
1494 #endif
1495 
1496 	flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 :
1497 	    AT_SYMLINK_NOFOLLOW;
1498 	error = kern_fchownat(td, dfd, path, UIO_SYSSPACE, args->uid, args->gid,
1499 	    flag);
1500 	LFREEPATH(path);
1501 	return (error);
1502 }
1503 
1504 int
1505 linux_lchown(struct thread *td, struct linux_lchown_args *args)
1506 {
1507 	char *path;
1508 	int error;
1509 
1510 	LCONVPATHEXIST(td, args->path, &path);
1511 
1512 #ifdef DEBUG
1513 	if (ldebug(lchown))
1514 		printf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid);
1515 #endif
1516 	error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, args->uid,
1517 	    args->gid, AT_SYMLINK_NOFOLLOW);
1518 	LFREEPATH(path);
1519 	return (error);
1520 }
1521 
1522 static int
1523 convert_fadvice(int advice)
1524 {
1525 	switch (advice) {
1526 	case LINUX_POSIX_FADV_NORMAL:
1527 		return (POSIX_FADV_NORMAL);
1528 	case LINUX_POSIX_FADV_RANDOM:
1529 		return (POSIX_FADV_RANDOM);
1530 	case LINUX_POSIX_FADV_SEQUENTIAL:
1531 		return (POSIX_FADV_SEQUENTIAL);
1532 	case LINUX_POSIX_FADV_WILLNEED:
1533 		return (POSIX_FADV_WILLNEED);
1534 	case LINUX_POSIX_FADV_DONTNEED:
1535 		return (POSIX_FADV_DONTNEED);
1536 	case LINUX_POSIX_FADV_NOREUSE:
1537 		return (POSIX_FADV_NOREUSE);
1538 	default:
1539 		return (-1);
1540 	}
1541 }
1542 
1543 int
1544 linux_fadvise64(struct thread *td, struct linux_fadvise64_args *args)
1545 {
1546 	int advice;
1547 
1548 	advice = convert_fadvice(args->advice);
1549 	if (advice == -1)
1550 		return (EINVAL);
1551 	return (kern_posix_fadvise(td, args->fd, args->offset, args->len,
1552 	    advice));
1553 }
1554 
1555 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1556 int
1557 linux_fadvise64_64(struct thread *td, struct linux_fadvise64_64_args *args)
1558 {
1559 	int advice;
1560 
1561 	advice = convert_fadvice(args->advice);
1562 	if (advice == -1)
1563 		return (EINVAL);
1564 	return (kern_posix_fadvise(td, args->fd, args->offset, args->len,
1565 	    advice));
1566 }
1567 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1568 
1569 int
1570 linux_pipe(struct thread *td, struct linux_pipe_args *args)
1571 {
1572 	int fildes[2];
1573 	int error;
1574 
1575 #ifdef DEBUG
1576 	if (ldebug(pipe))
1577 		printf(ARGS(pipe, "*"));
1578 #endif
1579 
1580 	error = kern_pipe(td, fildes, 0, NULL, NULL);
1581 	if (error != 0)
1582 		return (error);
1583 
1584 	error = copyout(fildes, args->pipefds, sizeof(fildes));
1585 	if (error != 0) {
1586 		(void)kern_close(td, fildes[0]);
1587 		(void)kern_close(td, fildes[1]);
1588 	}
1589 
1590 	return (error);
1591 }
1592 
1593 int
1594 linux_pipe2(struct thread *td, struct linux_pipe2_args *args)
1595 {
1596 	int fildes[2];
1597 	int error, flags;
1598 
1599 #ifdef DEBUG
1600 	if (ldebug(pipe2))
1601 		printf(ARGS(pipe2, "*, %d"), args->flags);
1602 #endif
1603 
1604 	if ((args->flags & ~(LINUX_O_NONBLOCK | LINUX_O_CLOEXEC)) != 0)
1605 		return (EINVAL);
1606 
1607 	flags = 0;
1608 	if ((args->flags & LINUX_O_NONBLOCK) != 0)
1609 		flags |= O_NONBLOCK;
1610 	if ((args->flags & LINUX_O_CLOEXEC) != 0)
1611 		flags |= O_CLOEXEC;
1612 	error = kern_pipe(td, fildes, flags, NULL, NULL);
1613 	if (error != 0)
1614 		return (error);
1615 
1616 	error = copyout(fildes, args->pipefds, sizeof(fildes));
1617 	if (error != 0) {
1618 		(void)kern_close(td, fildes[0]);
1619 		(void)kern_close(td, fildes[1]);
1620 	}
1621 
1622 	return (error);
1623 }
1624 
1625 int
1626 linux_dup3(struct thread *td, struct linux_dup3_args *args)
1627 {
1628 	int cmd;
1629 	intptr_t newfd;
1630 
1631 	if (args->oldfd == args->newfd)
1632 		return (EINVAL);
1633 	if ((args->flags & ~LINUX_O_CLOEXEC) != 0)
1634 		return (EINVAL);
1635 	if (args->flags & LINUX_O_CLOEXEC)
1636 		cmd = F_DUP2FD_CLOEXEC;
1637 	else
1638 		cmd = F_DUP2FD;
1639 
1640 	newfd = args->newfd;
1641 	return (kern_fcntl(td, args->oldfd, cmd, newfd));
1642 }
1643 
1644 int
1645 linux_fallocate(struct thread *td, struct linux_fallocate_args *args)
1646 {
1647 
1648 	/*
1649 	 * We emulate only posix_fallocate system call for which
1650 	 * mode should be 0.
1651 	 */
1652 	if (args->mode != 0)
1653 		return (ENOSYS);
1654 
1655 	return (kern_posix_fallocate(td, args->fd, args->offset,
1656 	    args->len));
1657 }
1658