Merge branch 'vendor/LIBPCAP'
[dragonfly.git] / sys / emulation / linux / linux_file.c
1 /*-
2  * Copyright (c) 1994-1995 Søren Schmidt
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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
16  *
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.
27  *
28  * $FreeBSD: src/sys/compat/linux/linux_file.c,v 1.41.2.6 2003/01/06 09:19:43 fjoe Exp $
29  */
30
31 #include "opt_compat.h"
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/conf.h>
36 #include <sys/dirent.h>
37 #include <sys/fcntl.h>
38 #include <sys/file.h>
39 #include <sys/stat.h>
40 #include <sys/filedesc.h>
41 #include <sys/kern_syscall.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/mount.h>
45 #include <sys/nlookup.h>
46 #include <sys/proc.h>
47 #include <sys/sysproto.h>
48 #include <sys/tty.h>
49 #include <sys/vnode.h>
50
51 #include <vfs/ufs/quota.h>
52 #include <vfs/ufs/ufsmount.h>
53
54 #include <sys/file2.h>
55 #include <sys/mplock2.h>
56
57 #include <arch_linux/linux.h>
58 #include <arch_linux/linux_proto.h>
59 #include "linux_util.h"
60
61 /*
62  * MPALMOSTSAFE
63  */
64 int
65 sys_linux_creat(struct linux_creat_args *args)
66 {
67         struct nlookupdata nd;
68         char *path;
69         int error;
70
71         error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
72         if (error)
73                 return (error);
74 #ifdef DEBUG
75         if (ldebug(creat))
76                 kprintf(ARGS(creat, "%s, %d"), path, args->mode);
77 #endif
78         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
79         if (error == 0) {
80                 error = kern_open(&nd, O_WRONLY | O_CREAT | O_TRUNC,
81                                   args->mode, &args->sysmsg_iresult);
82         }
83         linux_free_path(&path);
84         return(error);
85 }
86
87 /*
88  * MPALMOSTSAFE
89  */
90 static int
91 linux_open_common(int dfd, char *lpath, int lflags, int mode, int *iresult)
92 {
93         struct thread *td = curthread;
94         struct proc *p = td->td_proc;
95         struct nlookupdata nd;
96         struct file *fp;
97         char *path;
98         int error, flags;
99
100         if (lflags & LINUX_O_CREAT) {
101                 error = linux_copyin_path(lpath, &path,
102                     LINUX_PATH_CREATE);
103         } else {
104                 error = linux_copyin_path(lpath, &path,
105                     LINUX_PATH_EXISTS);
106         }
107         if (error)
108                 return (error);
109
110         flags = 0;
111         if (lflags & LINUX_O_RDONLY)
112                 flags |= O_RDONLY;
113         if (lflags & LINUX_O_WRONLY)
114                 flags |= O_WRONLY;
115         if (lflags & LINUX_O_RDWR)
116                 flags |= O_RDWR;
117         if (lflags & LINUX_O_NDELAY)
118                 flags |= O_NONBLOCK;
119         if (lflags & LINUX_O_APPEND)
120                 flags |= O_APPEND;
121         if (lflags & LINUX_O_SYNC)
122                 flags |= O_FSYNC;
123         if (lflags & LINUX_O_NONBLOCK)
124                 flags |= O_NONBLOCK;
125         if (lflags & LINUX_FASYNC)
126                 flags |= O_ASYNC;
127         if (lflags & LINUX_O_CREAT)
128                 flags |= O_CREAT;
129         if (lflags & LINUX_O_TRUNC)
130                 flags |= O_TRUNC;
131         if (lflags & LINUX_O_EXCL)
132                 flags |= O_EXCL;
133         if (lflags & LINUX_O_NOCTTY)
134                 flags |= O_NOCTTY;
135
136         error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, NLC_FOLLOW);
137         if (error == 0) {
138                 error = kern_open(&nd, flags, mode, iresult);
139         }
140         nlookup_done_at(&nd, fp);
141
142         if (error == 0 && !(flags & O_NOCTTY) && 
143                 SESS_LEADER(p) && !(p->p_flags & P_CONTROLT)) {
144                 struct file *fp;
145
146                 fp = holdfp(p->p_fd, *iresult, -1);
147                 if (fp) {
148                         if (fp->f_type == DTYPE_VNODE) {
149                                 fo_ioctl(fp, TIOCSCTTY, NULL,
150                                          td->td_ucred, NULL);
151                         }
152                         fdrop(fp);
153                 }
154         }
155
156         if (error == 0 && lflags & LINUX_O_DIRECTORY) {
157                 struct file *fp;
158                 struct vnode *vp;
159
160                 fp = holdfp(p->p_fd, *iresult, -1);
161                 if (fp) {
162                         vp = (struct vnode *) fp->f_data;
163                         if (vp->v_type != VDIR)
164                                 error = ENOTDIR;
165                         fdrop(fp);
166
167                         if (error)
168                                 kern_close(*iresult);
169                 }
170         }
171
172         linux_free_path(&path);
173         return error;
174 }
175
176 int
177 sys_linux_open(struct linux_open_args *args)
178 {
179         int error;
180
181 #ifdef DEBUG
182         if (ldebug(open))
183                 kprintf(ARGS(open, "%s, 0x%x, 0x%x"), args->path, args->flags,
184                     args->mode);
185 #endif
186
187         error = linux_open_common(AT_FDCWD, args->path, args->flags,
188             args->mode, &args->sysmsg_iresult);
189
190 #ifdef DEBUG
191         if (ldebug(open))
192                 kprintf(LMSG("open returns error %d"), error);
193 #endif
194         return error;
195 }
196
197 int
198 sys_linux_openat(struct linux_openat_args *args)
199 {
200         int error;
201         int dfd;
202
203 #ifdef DEBUG
204         if (ldebug(openat))
205                 kprintf(ARGS(openat, "%s, 0x%x, 0x%x"), args->path,
206                     args->flags, args->mode);
207 #endif
208
209         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
210
211         error = linux_open_common(dfd, args->path, args->flags,
212             args->mode, &args->sysmsg_iresult);
213
214 #ifdef DEBUG
215         if (ldebug(openat))
216                 kprintf(LMSG("openat returns error %d"), error);
217 #endif
218         return error;
219 }
220
221 /*
222  * MPSAFE
223  */
224 int
225 sys_linux_lseek(struct linux_lseek_args *args)
226 {
227         int error;
228
229 #ifdef DEBUG
230         if (ldebug(lseek))
231                 kprintf(ARGS(lseek, "%d, %ld, %d"),
232                     args->fdes, (long)args->off, args->whence);
233 #endif
234         error = kern_lseek(args->fdes, args->off, args->whence,
235                            &args->sysmsg_offset);
236
237         return error;
238 }
239
240 /*
241  * MPSAFE
242  */
243 int
244 sys_linux_llseek(struct linux_llseek_args *args)
245 {
246         int error;
247         off_t off, res;
248
249 #ifdef DEBUG
250         if (ldebug(llseek))
251                 kprintf(ARGS(llseek, "%d, %d:%d, %d"),
252                     args->fd, args->ohigh, args->olow, args->whence);
253 #endif
254         off = (args->olow) | (((off_t) args->ohigh) << 32);
255
256         error = kern_lseek(args->fd, off, args->whence, &res);
257
258         if (error == 0)
259                 error = copyout(&res, args->res, sizeof(res));
260         return (error);
261 }
262
263 /*
264  * MPSAFE
265  */
266 int
267 sys_linux_readdir(struct linux_readdir_args *args)
268 {
269         struct linux_getdents_args lda;
270         int error;
271
272         lda.fd = args->fd;
273         lda.dent = args->dent;
274         lda.count = -1;
275         lda.sysmsg_iresult = 0;
276         error = sys_linux_getdents(&lda);
277         args->sysmsg_iresult = lda.sysmsg_iresult;
278         return(error);
279 }
280
281 /*
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...
288  */
289
290 struct l_dirent {
291         l_long          d_ino;
292         l_off_t         d_off;
293         l_ushort        d_reclen;
294         char            d_name[LINUX_NAME_MAX + 1];
295 };
296
297 struct l_dirent64 {
298         uint64_t        d_ino;
299         int64_t         d_off;
300         l_ushort        d_reclen;
301         u_char          d_type;
302         char            d_name[LINUX_NAME_MAX + 1];
303 };
304
305 #define LINUX_RECLEN(de,namlen) \
306     ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
307
308 #define LINUX_DIRBLKSIZ         512
309
310 /*
311  * MPALMOSTSAFE
312  */
313 static int
314 getdents_common(struct linux_getdents64_args *args, int is64bit)
315 {
316         struct thread *td = curthread;
317         struct proc *p = td->td_proc;
318         struct dirent *bdp;
319         struct vnode *vp;
320         caddr_t inp, buf;               /* BSD-format */
321         int reclen;                     /* BSD-format */
322         size_t len;
323         caddr_t outp;                   /* Linux-format */
324         int linuxreclen = 0;            /* Linux-format */
325         size_t resid;
326         struct file *fp;
327         struct uio auio;
328         struct iovec aiov;
329         struct vattr va;
330         off_t off;
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;
336         int ncookies;
337
338         if ((error = holdvnode(p->p_fd, args->fd, &fp)) != 0)
339                 return (error);
340
341         get_mplock();
342         if ((fp->f_flag & FREAD) == 0) {
343                 error = EBADF;
344                 goto done;
345         }
346
347         vp = (struct vnode *) fp->f_data;
348         if (vp->v_type != VDIR) {
349                 error = EINVAL;
350                 goto done;
351         }
352
353         if ((error = VOP_GETATTR(vp, &va)) != 0)
354                 goto done;
355
356         nbytes = args->count;
357         if (nbytes == (size_t)-1) {
358                 /* readdir(2) case. Always struct dirent. */
359                 if (is64bit) {
360                         error = EINVAL;
361                         goto done;
362                 }
363                 nbytes = sizeof(linux_dirent);
364                 justone = 1;
365         } else {
366                 justone = 0;
367         }
368         if ((ssize_t)nbytes < 0)
369                 nbytes = 0;
370
371         off = fp->f_offset;
372
373         buflen = max(LINUX_DIRBLKSIZ, nbytes);
374         buflen = min(buflen, MAXBSIZE);
375         buf = kmalloc(buflen, M_TEMP, M_WAITOK);
376
377 again:
378         aiov.iov_base = buf;
379         aiov.iov_len = buflen;
380         auio.uio_iov = &aiov;
381         auio.uio_iovcnt = 1;
382         auio.uio_rw = UIO_READ;
383         auio.uio_segflg = UIO_SYSSPACE;
384         auio.uio_td = td;
385         auio.uio_resid = buflen;
386         auio.uio_offset = off;
387
388         if (cookies) {
389                 kfree(cookies, M_TEMP);
390                 cookies = NULL;
391         }
392
393         eofflag = 0;
394         ncookies = 0;
395         if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
396                  &cookies)))
397                 goto out;
398
399         inp = buf;
400         outp = (caddr_t)args->dirent;
401         resid = nbytes;
402         if (auio.uio_resid >= buflen)
403                 goto eof;
404         len = buflen - auio.uio_resid;
405         cookiep = cookies;
406
407         if (cookies) {
408                 /*
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).
414                  */
415                 while (len > 0 && ncookies > 0 && *cookiep < off) {
416                         bdp = (struct dirent *) inp;
417                         len -= _DIRENT_DIRSIZ(bdp);
418                         inp += _DIRENT_DIRSIZ(bdp);
419                         cookiep++;
420                         ncookies--;
421                 }
422         }
423
424         while (len > 0) {
425                 if (cookiep && ncookies == 0)
426                         break;
427                 bdp = (struct dirent *) inp;
428                 reclen = _DIRENT_DIRSIZ(bdp);
429                 if (reclen & 3) {
430                         error = EFAULT;
431                         goto out;
432                 }
433
434                 if (bdp->d_ino == 0) {
435                         inp += reclen;
436                         if (cookiep) {
437                                 off = *cookiep++;
438                                 ++off;
439                                 ncookies--;
440                         } else {
441                                 off += reclen;
442                         }
443                         len -= reclen;
444                         continue;
445                 }
446
447                 linuxreclen = (is64bit)
448                     ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen)
449                     : LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
450
451                 if (reclen > len || resid < linuxreclen) {
452                         outp++;
453                         break;
454                 }
455
456                 bzero(&linux_dirent, sizeof(linux_dirent));
457                 bzero(&linux_dirent64, sizeof(linux_dirent64));
458                 if (justone) {
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);
465                 } else {
466                         if (is64bit) {
467                                 linux_dirent64.d_ino = INO64TO32(bdp->d_ino);
468                                 linux_dirent64.d_off = (cookiep)
469                                     ? (l_off_t)*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,
476                                     linuxreclen);
477                         } else {
478                                 linux_dirent.d_ino = INO64TO32(bdp->d_ino);
479                                 linux_dirent.d_off = (cookiep)
480                                     ? (l_off_t)*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,
485                                     linuxreclen);
486                         }
487                 }
488                 if (error)
489                         goto out;
490
491                 inp += reclen;
492                 if (cookiep) {
493                         off = *cookiep++;
494                         ++off;
495                         ncookies--;
496                 } else {
497                         off += reclen;
498                 }
499
500                 outp += linuxreclen;
501                 resid -= linuxreclen;
502                 len -= reclen;
503                 if (justone)
504                         break;
505         }
506
507         if (outp == (caddr_t)args->dirent && eofflag == 0)
508                 goto again;
509
510         fp->f_offset = off;
511         if (justone)
512                 nbytes = resid + linuxreclen;
513
514 eof:
515         args->sysmsg_iresult = (int)(nbytes - resid);
516
517 out:
518         if (cookies)
519                 kfree(cookies, M_TEMP);
520
521         kfree(buf, M_TEMP);
522 done:
523         rel_mplock();
524         fdrop(fp);
525         return (error);
526 }
527
528 /*
529  * MPSAFE
530  */
531 int
532 sys_linux_getdents(struct linux_getdents_args *args)
533 {
534 #ifdef DEBUG
535         if (ldebug(getdents))
536                 kprintf(ARGS(getdents, "%d, *, %d"), args->fd, args->count);
537 #endif
538         return (getdents_common((struct linux_getdents64_args*)args, 0));
539 }
540
541 /*
542  * MPSAFE
543  */
544 int
545 sys_linux_getdents64(struct linux_getdents64_args *args)
546 {
547 #ifdef DEBUG
548         if (ldebug(getdents64))
549                 kprintf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count);
550 #endif
551         return (getdents_common(args, 1));
552 }
553
554 /*
555  * These exist mainly for hooks for doing /compat/linux translation.
556  *
557  * MPALMOSTSAFE
558  */
559 int
560 sys_linux_access(struct linux_access_args *args)
561 {
562         struct nlookupdata nd;
563         char *path;
564         int error;
565
566         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
567         if (error)
568                 return (error);
569 #ifdef DEBUG
570         if (ldebug(access))
571                 kprintf(ARGS(access, "%s, %d"), path, args->flags);
572 #endif
573         get_mplock();
574         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
575         if (error == 0)
576                 error = kern_access(&nd, args->flags, 0);
577         nlookup_done(&nd);
578         rel_mplock();
579         linux_free_path(&path);
580         return(error);
581 }
582
583 /*
584  * MPALMOSTSAFE
585  */
586 int
587 sys_linux_unlink(struct linux_unlink_args *args)
588 {
589         struct nlookupdata nd;
590         char *path;
591         int error;
592
593         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
594         if (error)
595                 return (error);
596 #ifdef DEBUG
597         if (ldebug(unlink))
598                 kprintf(ARGS(unlink, "%s"), path);
599 #endif
600         get_mplock();
601         error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
602         if (error == 0)
603                 error = kern_unlink(&nd);
604         nlookup_done(&nd);
605         rel_mplock();
606         linux_free_path(&path);
607         return(error);
608 }
609
610 int
611 sys_linux_unlinkat(struct linux_unlinkat_args *args)
612 {
613         struct nlookupdata nd;
614         struct file *fp;
615         char *path;
616         int dfd, error;
617
618         if (args->flag & ~LINUX_AT_REMOVEDIR)
619                 return (EINVAL);
620
621         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
622         if (error) {
623                 kprintf("linux_copyin_path says error = %d\n", error);
624                 return (error);
625         }
626 #ifdef DEBUG
627         if (ldebug(unlink))
628                 kprintf(ARGS(unlink, "%s"), path);
629 #endif
630
631         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
632         get_mplock();
633         error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
634         if (error == 0) {
635                 if (args->flag & LINUX_AT_REMOVEDIR)
636                         error = kern_rmdir(&nd);
637                 else
638                         error = kern_unlink(&nd);
639         }
640         nlookup_done_at(&nd, fp);
641         rel_mplock();
642         linux_free_path(&path);
643         return(error);
644 }
645
646 /*
647  * MPALMOSTSAFE
648  */
649 int
650 sys_linux_chdir(struct linux_chdir_args *args)
651 {
652         struct nlookupdata nd;
653         char *path;
654         int error;
655
656         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
657         if (error)
658                 return (error);
659 #ifdef DEBUG
660         if (ldebug(chdir))
661                 kprintf(ARGS(chdir, "%s"), path);
662 #endif
663         get_mplock();
664         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
665         if (error == 0) {
666                 error = kern_chdir(&nd);
667                 nlookup_done(&nd);
668         }
669         rel_mplock();
670         linux_free_path(&path);
671         return(error);
672 }
673
674 /*
675  * MPALMOSTSAFE
676  */
677 int
678 sys_linux_chmod(struct linux_chmod_args *args)
679 {
680         struct nlookupdata nd;
681         char *path;
682         int error;
683
684         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
685         if (error)
686                 return (error);
687 #ifdef DEBUG
688         if (ldebug(chmod))
689                 kprintf(ARGS(chmod, "%s, %d"), path, args->mode);
690 #endif
691         get_mplock();
692         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
693         if (error == 0)
694                 error = kern_chmod(&nd, args->mode);
695         nlookup_done(&nd);
696         rel_mplock();
697         linux_free_path(&path);
698         return(error);
699 }
700
701 /*
702  * MPALMOSTSAFE
703  */
704 int
705 sys_linux_mkdir(struct linux_mkdir_args *args)
706 {
707         struct nlookupdata nd;
708         char *path;
709         int error;
710
711         error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
712         if (error)
713                 return (error);
714 #ifdef DEBUG
715         if (ldebug(mkdir))
716                 kprintf(ARGS(mkdir, "%s, %d"), path, args->mode);
717 #endif
718         get_mplock();
719         error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
720         if (error == 0)
721                 error = kern_mkdir(&nd, args->mode);
722         nlookup_done(&nd);
723         rel_mplock();
724
725         linux_free_path(&path);
726         return(error);
727 }
728
729 int
730 sys_linux_mkdirat(struct linux_mkdirat_args *args)
731 {
732         struct nlookupdata nd;
733         struct file *fp;
734         char *path;
735         int dfd, error;
736
737         error = linux_copyin_path(args->path, &path, LINUX_PATH_CREATE);
738         if (error)
739                 return (error);
740 #ifdef DEBUG
741         if (ldebug(mkdir))
742                 kprintf(ARGS(mkdir, "%s, %d"), path, args->mode);
743 #endif
744         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
745         get_mplock();
746         error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
747         if (error == 0)
748                 error = kern_mkdir(&nd, args->mode);
749         nlookup_done_at(&nd, fp);
750         rel_mplock();
751
752         linux_free_path(&path);
753         return(error);
754 }
755
756 /*
757  * MPALMOSTSAFE
758  */
759 int
760 sys_linux_rmdir(struct linux_rmdir_args *args)
761 {
762         struct nlookupdata nd;
763         char *path;
764         int error;
765
766         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
767         if (error)
768                 return (error);
769 #ifdef DEBUG
770         if (ldebug(rmdir))
771                 kprintf(ARGS(rmdir, "%s"), path);
772 #endif
773         get_mplock();
774         error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
775         if (error == 0)
776                 error = kern_rmdir(&nd);
777         nlookup_done(&nd);
778         rel_mplock();
779         linux_free_path(&path);
780         return(error);
781 }
782
783 /*
784  * MPALMOSTSAFE
785  */
786 int
787 sys_linux_rename(struct linux_rename_args *args)
788 {
789         struct nlookupdata fromnd, tond;
790         char *from, *to;
791         int error;
792
793         error = linux_copyin_path(args->from, &from, LINUX_PATH_EXISTS);
794         if (error)
795                 return (error);
796         error = linux_copyin_path(args->to, &to, LINUX_PATH_CREATE);
797         if (error) {
798                 linux_free_path(&from);
799                 return (error);
800         }
801 #ifdef DEBUG
802         if (ldebug(rename))
803                 kprintf(ARGS(rename, "%s, %s"), from, to);
804 #endif
805         get_mplock();
806         error = nlookup_init(&fromnd, from, UIO_SYSSPACE, 0);
807         if (error == 0) {
808                 error = nlookup_init(&tond, to, UIO_SYSSPACE, 0);
809                 if (error == 0)
810                         error = kern_rename(&fromnd, &tond);
811                 nlookup_done(&tond);
812         }
813         nlookup_done(&fromnd);
814         rel_mplock();
815         linux_free_path(&from);
816         linux_free_path(&to);
817         return(error);
818 }
819
820 int
821 sys_linux_renameat(struct linux_renameat_args *args)
822 {
823         struct nlookupdata fromnd, tond;
824         struct file *fp, *fp2;
825         char *from, *to;
826         int olddfd, newdfd,error;
827
828         error = linux_copyin_path(args->from, &from, LINUX_PATH_EXISTS);
829         if (error)
830                 return (error);
831         error = linux_copyin_path(args->to, &to, LINUX_PATH_CREATE);
832         if (error) {
833                 linux_free_path(&from);
834                 return (error);
835         }
836 #ifdef DEBUG
837         if (ldebug(rename))
838                 kprintf(ARGS(rename, "%s, %s"), from, to);
839 #endif
840         olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
841         newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
842         get_mplock();
843         error = nlookup_init_at(&fromnd, &fp, olddfd, from, UIO_SYSSPACE, 0);
844         if (error == 0) {
845                 error = nlookup_init_at(&tond, &fp2, newdfd, to, UIO_SYSSPACE, 0);
846                 if (error == 0)
847                         error = kern_rename(&fromnd, &tond);
848                 nlookup_done_at(&tond, fp2);
849         }
850         nlookup_done_at(&fromnd, fp);
851         rel_mplock();
852         linux_free_path(&from);
853         linux_free_path(&to);
854         return(error);
855 }
856
857 /*
858  * MPALMOSTSAFE
859  */
860 int
861 sys_linux_symlink(struct linux_symlink_args *args)
862 {
863         struct thread *td = curthread;
864         struct nlookupdata nd;
865         char *path, *link;
866         int error;
867         int mode;
868
869         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
870         if (error)
871                 return (error);
872         error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
873         if (error) {
874                 linux_free_path(&path);
875                 return (error);
876         }
877 #ifdef DEBUG
878         if (ldebug(symlink))
879                 kprintf(ARGS(symlink, "%s, %s"), path, link);
880 #endif
881         get_mplock();
882         error = nlookup_init(&nd, link, UIO_SYSSPACE, 0);
883         if (error == 0) {
884                 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
885                 error = kern_symlink(&nd, path, mode);
886         }
887         nlookup_done(&nd);
888         rel_mplock();
889         linux_free_path(&path);
890         linux_free_path(&link);
891         return(error);
892 }
893
894 int
895 sys_linux_symlinkat(struct linux_symlinkat_args *args)
896 {
897         struct thread *td = curthread;
898         struct nlookupdata nd;
899         struct file *fp;
900         char *path, *link;
901         int error;
902         int newdfd, mode;
903
904         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
905         if (error)
906                 return (error);
907         error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
908         if (error) {
909                 linux_free_path(&path);
910                 return (error);
911         }
912 #ifdef DEBUG
913         if (ldebug(symlink))
914                 kprintf(ARGS(symlink, "%s, %s"), path, link);
915 #endif
916         newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
917         get_mplock();
918         error = nlookup_init_at(&nd, &fp, newdfd, link, UIO_SYSSPACE, 0);
919         if (error == 0) {
920                 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
921                 error = kern_symlink(&nd, path, mode);
922         }
923         nlookup_done_at(&nd, fp);
924         rel_mplock();
925         linux_free_path(&path);
926         linux_free_path(&link);
927         return(error);
928 }
929
930 /*
931  * MPALMOSTSAFE
932  */
933 int
934 sys_linux_readlink(struct linux_readlink_args *args)
935 {
936         struct nlookupdata nd;
937         char *path;
938         int error;
939
940         error = linux_copyin_path(args->name, &path, LINUX_PATH_EXISTS);
941         if (error)
942                 return (error);
943 #ifdef DEBUG
944         if (ldebug(readlink))
945                 kprintf(ARGS(readlink, "%s, %p, %d"), path, (void *)args->buf,
946                     args->count);
947 #endif
948         get_mplock();
949         error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
950         if (error == 0) {
951                 error = kern_readlink(&nd, args->buf, args->count,
952                                       &args->sysmsg_iresult);
953         }
954         nlookup_done(&nd);
955         rel_mplock();
956         linux_free_path(&path);
957         return(error);
958 }
959
960 int
961 sys_linux_readlinkat(struct linux_readlinkat_args *args)
962 {
963         struct nlookupdata nd;
964         struct file *fp;
965         char *path;
966         int dfd, error;
967
968         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
969         if (error)
970                 return (error);
971 #ifdef DEBUG
972         if (ldebug(readlink))
973                 kprintf(ARGS(readlink, "%s, %p, %d"), path, (void *)args->buf,
974                     args->count);
975 #endif
976         dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
977         get_mplock();
978         error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
979         if (error == 0) {
980                 error = kern_readlink(&nd, args->buf, args->count,
981                                       &args->sysmsg_iresult);
982         }
983         nlookup_done_at(&nd, fp);
984         rel_mplock();
985         linux_free_path(&path);
986         return(error);
987 }
988
989 /*
990  * MPALMOSTSAFE
991  */
992 int
993 sys_linux_truncate(struct linux_truncate_args *args)
994 {
995         struct nlookupdata nd;
996         char *path;
997         int error;
998
999         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1000         if (error)
1001                 return (error);
1002 #ifdef DEBUG
1003         if (ldebug(truncate))
1004                 kprintf(ARGS(truncate, "%s, %ld"), path,
1005                     (long)args->length);
1006 #endif
1007         get_mplock();
1008         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1009         if (error == 0)
1010                 error = kern_truncate(&nd, args->length);
1011         nlookup_done(&nd);
1012         rel_mplock();
1013         linux_free_path(&path);
1014         return(error);
1015 }
1016
1017 /*
1018  * MPALMOSTSAFE
1019  */
1020 int
1021 sys_linux_truncate64(struct linux_truncate64_args *args)
1022 {
1023         struct nlookupdata nd;
1024         char *path;
1025         int error;
1026
1027         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1028         if (error)
1029                 return (error);
1030 #ifdef DEBUG
1031         if (ldebug(truncate64))
1032                 kprintf(ARGS(truncate64, "%s, %lld"), path,
1033                     (off_t)args->length);
1034 #endif
1035         get_mplock();
1036         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1037         if (error == 0)
1038                 error = kern_truncate(&nd, args->length);
1039         nlookup_done(&nd);
1040         rel_mplock();
1041         linux_free_path(&path);
1042         return error;
1043 }
1044
1045 /*
1046  * MPALMOSTSAFE
1047  */
1048 int
1049 sys_linux_ftruncate(struct linux_ftruncate_args *args)
1050 {
1051         int error;
1052
1053 #ifdef DEBUG
1054         if (ldebug(ftruncate))
1055                 kprintf(ARGS(ftruncate, "%d, %ld"), args->fd,
1056                     (long)args->length);
1057 #endif
1058         get_mplock();
1059         error = kern_ftruncate(args->fd, args->length);
1060         rel_mplock();
1061
1062         return error;
1063 }
1064
1065 /*
1066  * MPALMOSTSAFE
1067  */
1068 int
1069 sys_linux_ftruncate64(struct linux_ftruncate64_args *args)
1070 {
1071         int error;
1072
1073 #ifdef DEBUG
1074         if (ldebug(ftruncate))
1075                 kprintf(ARGS(ftruncate64, "%d, %lld"), args->fd,
1076                     (off_t)args->length);
1077 #endif
1078         get_mplock();
1079         error = kern_ftruncate(args->fd, args->length);
1080         rel_mplock();
1081
1082         return error;
1083 }
1084
1085 /*
1086  * MPALMOSTSAFE
1087  */
1088 int
1089 sys_linux_link(struct linux_link_args *args)
1090 {
1091         struct nlookupdata nd, linknd;
1092         char *path, *link;
1093         int error;
1094
1095         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1096         if (error)
1097                 return (error);
1098         error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
1099         if (error) {
1100                 linux_free_path(&path);
1101                 return (error);
1102         }
1103 #ifdef DEBUG
1104         if (ldebug(link))
1105                 kprintf(ARGS(link, "%s, %s"), path, link);
1106 #endif
1107         get_mplock();
1108         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1109         if (error == 0) {
1110                 error = nlookup_init(&linknd, link, UIO_SYSSPACE, 0);
1111                 if (error == 0)
1112                         error = kern_link(&nd, &linknd);
1113                 nlookup_done(&linknd);
1114         }
1115         nlookup_done(&nd);
1116         rel_mplock();
1117         linux_free_path(&path);
1118         linux_free_path(&link);
1119         return(error);
1120 }
1121
1122 int
1123 sys_linux_linkat(struct linux_linkat_args *args)
1124 {
1125         struct nlookupdata nd, linknd;
1126         struct file *fp, *fp2;
1127         char *path, *link;
1128         int olddfd, newdfd, error;
1129
1130         if (args->flags != 0)
1131                 return (EINVAL);
1132
1133         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1134         if (error)
1135                 return (error);
1136         error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
1137         if (error) {
1138                 linux_free_path(&path);
1139                 return (error);
1140         }
1141 #ifdef DEBUG
1142         if (ldebug(link))
1143                 kprintf(ARGS(link, "%s, %s"), path, link);
1144 #endif
1145         olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
1146         newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
1147         get_mplock();
1148         error = nlookup_init_at(&nd, &fp, olddfd, path, UIO_SYSSPACE, NLC_FOLLOW);
1149         if (error == 0) {
1150                 error = nlookup_init_at(&linknd, &fp2, newdfd, link, UIO_SYSSPACE, 0);
1151                 if (error == 0)
1152                         error = kern_link(&nd, &linknd);
1153                 nlookup_done_at(&linknd, fp2);
1154         }
1155         nlookup_done_at(&nd, fp);
1156         rel_mplock();
1157         linux_free_path(&path);
1158         linux_free_path(&link);
1159         return(error);
1160 }
1161
1162 /*
1163  * MPSAFE
1164  */
1165 int
1166 sys_linux_fdatasync(struct linux_fdatasync_args *uap)
1167 {
1168         struct fsync_args bsd;
1169         int error;
1170
1171         bsd.fd = uap->fd;
1172         bsd.sysmsg_iresult = 0;
1173
1174         error = sys_fsync(&bsd);
1175         uap->sysmsg_iresult = bsd.sysmsg_iresult;
1176         return(error);
1177 }
1178
1179 /*
1180  * MPSAFE
1181  */
1182 int
1183 sys_linux_pread(struct linux_pread_args *uap)
1184 {
1185         struct thread *td = curthread;
1186         struct uio auio;
1187         struct iovec aiov;
1188         int error;
1189
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;
1198         auio.uio_td = td;
1199
1200         if ((ssize_t)auio.uio_resid < 0) {
1201                 error = EINVAL;
1202         } else {
1203                 error = kern_preadv(uap->fd, &auio, O_FOFFSET,
1204                                     &uap->sysmsg_szresult);
1205         }
1206         return(error);
1207 }
1208
1209 /*
1210  * MPSAFE
1211  */
1212 int
1213 sys_linux_pwrite(struct linux_pwrite_args *uap)
1214 {
1215         struct thread *td = curthread;
1216         struct uio auio;
1217         struct iovec aiov;
1218         int error;
1219
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;
1228         auio.uio_td = td;
1229
1230         if ((ssize_t)auio.uio_resid < 0) {
1231                 error = EINVAL;
1232         } else {
1233                 error = kern_pwritev(uap->fd, &auio, O_FOFFSET,
1234                                      &uap->sysmsg_szresult);
1235         }
1236         return(error);
1237 }
1238
1239 /*
1240  * MPSAFE
1241  */
1242 int
1243 sys_linux_oldumount(struct linux_oldumount_args *args)
1244 {
1245         struct linux_umount_args args2;
1246         int error;
1247
1248         args2.path = args->path;
1249         args2.flags = 0;
1250         args2.sysmsg_iresult = 0;
1251         error = sys_linux_umount(&args2);
1252         args->sysmsg_iresult = args2.sysmsg_iresult;
1253         return(error);
1254 }
1255
1256 /*
1257  * MPSAFE
1258  */
1259 int
1260 sys_linux_umount(struct linux_umount_args *args)
1261 {
1262         struct unmount_args bsd;
1263         int error;
1264
1265         bsd.path = args->path;
1266         bsd.flags = args->flags;        /* XXX correct? */
1267         bsd.sysmsg_iresult = 0;
1268
1269         error = sys_unmount(&bsd);
1270         args->sysmsg_iresult = bsd.sysmsg_iresult;
1271         return(error);
1272 }
1273
1274 /*
1275  * fcntl family of syscalls
1276  */
1277 struct l_flock {
1278         l_short         l_type;
1279         l_short         l_whence;
1280         l_off_t         l_start;
1281         l_off_t         l_len;
1282         l_pid_t         l_pid;
1283 };
1284
1285 /*
1286  * MPSAFE
1287  */
1288 static void
1289 linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
1290 {
1291         switch (linux_flock->l_type) {
1292         case LINUX_F_RDLCK:
1293                 bsd_flock->l_type = F_RDLCK;
1294                 break;
1295         case LINUX_F_WRLCK:
1296                 bsd_flock->l_type = F_WRLCK;
1297                 break;
1298         case LINUX_F_UNLCK:
1299                 bsd_flock->l_type = F_UNLCK;
1300                 break;
1301         default:
1302                 bsd_flock->l_type = -1;
1303                 break;
1304         }
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;
1309 }
1310
1311 /*
1312  * MPSAFE
1313  */
1314 static void
1315 bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
1316 {
1317         switch (bsd_flock->l_type) {
1318         case F_RDLCK:
1319                 linux_flock->l_type = LINUX_F_RDLCK;
1320                 break;
1321         case F_WRLCK:
1322                 linux_flock->l_type = LINUX_F_WRLCK;
1323                 break;
1324         case F_UNLCK:
1325                 linux_flock->l_type = LINUX_F_UNLCK;
1326                 break;
1327         }
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;
1332 }
1333
1334 #if defined(__i386__)
1335 struct l_flock64 {
1336         l_short         l_type;
1337         l_short         l_whence;
1338         l_loff_t        l_start;
1339         l_loff_t        l_len;
1340         l_pid_t         l_pid;
1341 };
1342
1343 /*
1344  * MPSAFE
1345  */
1346 static void
1347 linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
1348 {
1349         switch (linux_flock->l_type) {
1350         case LINUX_F_RDLCK:
1351                 bsd_flock->l_type = F_RDLCK;
1352                 break;
1353         case LINUX_F_WRLCK:
1354                 bsd_flock->l_type = F_WRLCK;
1355                 break;
1356         case LINUX_F_UNLCK:
1357                 bsd_flock->l_type = F_UNLCK;
1358                 break;
1359         default:
1360                 bsd_flock->l_type = -1;
1361                 break;
1362         }
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;
1367 }
1368
1369 /*
1370  * MPSAFE
1371  */
1372 static void
1373 bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
1374 {
1375         switch (bsd_flock->l_type) {
1376         case F_RDLCK:
1377                 linux_flock->l_type = LINUX_F_RDLCK;
1378                 break;
1379         case F_WRLCK:
1380                 linux_flock->l_type = LINUX_F_WRLCK;
1381                 break;
1382         case F_UNLCK:
1383                 linux_flock->l_type = LINUX_F_UNLCK;
1384                 break;
1385         }
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;
1390 }
1391 #endif /* __i386__ */
1392
1393 /*
1394  * MPSAFE
1395  */
1396 static int
1397 linux_fcntl_common(struct linux_fcntl64_args *args)
1398 {
1399         struct thread *td = curthread;
1400         struct l_flock linux_flock;
1401         struct file *fp;
1402         union fcntl_dat dat;
1403         int error, cmd;
1404
1405         switch (args->cmd) {
1406         case LINUX_F_DUPFD:
1407                 cmd = F_DUPFD;
1408                 dat.fc_fd = args->arg;
1409                 break;
1410         case LINUX_F_GETFD:
1411                 cmd = F_GETFD;
1412                 break;
1413         case LINUX_F_SETFD:
1414                 cmd = F_SETFD;
1415                 dat.fc_cloexec = args->arg;
1416                 break;
1417         case LINUX_F_GETFL:
1418                 cmd = F_GETFL;
1419                 break;
1420         case LINUX_F_SETFL:
1421                 cmd = F_SETFL;
1422                 dat.fc_flags = 0;
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;
1431                 break;
1432         case LINUX_F_GETLK:
1433         case LINUX_F_SETLK:
1434         case LINUX_F_SETLKW:
1435                 cmd = F_GETLK;
1436                 error = copyin((caddr_t)args->arg, &linux_flock,
1437                     sizeof(linux_flock));
1438                 if (error)
1439                         return (error);
1440                 linux_to_bsd_flock(&linux_flock, &dat.fc_flock);
1441                 break;
1442         case LINUX_F_GETOWN:
1443                 cmd = F_GETOWN;
1444                 break;
1445         case LINUX_F_SETOWN:
1446                 /*
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).
1450                  */
1451                 fp = holdfp(td->td_proc->p_fd, args->fd, -1);
1452                 if (fp == NULL)
1453                         return (EBADF);
1454                 if (fp->f_type == DTYPE_PIPE) {
1455                         fdrop(fp);
1456                         return (EINVAL);
1457                 }
1458                 fdrop(fp);
1459                 cmd = F_SETOWN;
1460                 dat.fc_owner = args->arg;
1461                 break;
1462         default:
1463                 return (EINVAL);
1464         }
1465
1466         /* MPSAFE */
1467         error = kern_fcntl(args->fd, cmd, &dat, td->td_ucred);
1468
1469         if (error == 0) {
1470                 switch (args->cmd) {
1471                 case LINUX_F_DUPFD:
1472                         args->sysmsg_iresult = dat.fc_fd;
1473                         break;
1474                 case LINUX_F_GETFD:
1475                         args->sysmsg_iresult = dat.fc_cloexec;
1476                         break;
1477                 case LINUX_F_SETFD:
1478                         break;
1479                 case LINUX_F_GETFL:
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;
1495                         break;
1496                 case LINUX_F_GETLK:
1497                         bsd_to_linux_flock(&dat.fc_flock, &linux_flock);
1498                         error = copyout(&linux_flock, (caddr_t)args->arg,
1499                             sizeof(linux_flock));
1500                         break;
1501                 case LINUX_F_SETLK:
1502                 case LINUX_F_SETLKW:
1503                         break;
1504                 case LINUX_F_GETOWN:
1505                         args->sysmsg_iresult = dat.fc_owner;
1506                         break;
1507                 case LINUX_F_SETOWN:
1508                         break;
1509                 }
1510         }
1511
1512         return(error);
1513 }
1514
1515 /*
1516  * MPSAFE
1517  */
1518 int
1519 sys_linux_fcntl(struct linux_fcntl_args *args)
1520 {
1521         struct linux_fcntl64_args args64;
1522         int error;
1523
1524 #ifdef DEBUG
1525         if (ldebug(fcntl))
1526                 kprintf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
1527 #endif
1528
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;
1535         return(error);
1536 }
1537
1538 #if defined(__i386__)
1539 /*
1540  * MPSAFE
1541  */
1542 int
1543 sys_linux_fcntl64(struct linux_fcntl64_args *args)
1544 {
1545         struct thread *td = curthread;
1546         struct l_flock64 linux_flock;
1547         union fcntl_dat dat;
1548         int error, cmd = 0;
1549
1550 #ifdef DEBUG
1551         if (ldebug(fcntl64))
1552                 kprintf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd);
1553 #endif
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:
1558                         cmd = F_GETLK;
1559                         break;
1560                 case LINUX_F_SETLK64:
1561                         cmd = F_SETLK;
1562                         break;
1563                 case LINUX_F_SETLKW64:
1564                         cmd = F_SETLKW;
1565                         break;
1566                 }
1567
1568                 error = copyin((caddr_t)args->arg, &linux_flock,
1569                     sizeof(linux_flock));
1570                 if (error)
1571                         return (error);
1572                 linux_to_bsd_flock64(&linux_flock, &dat.fc_flock);
1573
1574                 /* MPSAFE */
1575                 error = kern_fcntl(args->fd, cmd, &dat, td->td_ucred);
1576
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));
1581                 }
1582         } else {
1583                 error = linux_fcntl_common(args);
1584         }
1585
1586         return (error);
1587 }
1588 #endif /* __i386__ */
1589
1590 /*
1591  * MPALMOSTSAFE
1592  */
1593 int
1594 sys_linux_chown(struct linux_chown_args *args)
1595 {
1596         struct nlookupdata nd;
1597         char *path;
1598         int error;
1599
1600         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1601         if (error)
1602                 return (error);
1603 #ifdef DEBUG
1604         if (ldebug(chown))
1605                 kprintf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid);
1606 #endif
1607         get_mplock();
1608         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1609         if (error == 0)
1610                 error = kern_chown(&nd, args->uid, args->gid);
1611         nlookup_done(&nd);
1612         rel_mplock();
1613         linux_free_path(&path);
1614         return(error);
1615 }
1616
1617 /*
1618  * MPALMOSTSAFE
1619  */
1620 int
1621 sys_linux_lchown(struct linux_lchown_args *args)
1622 {
1623         struct nlookupdata nd;
1624         char *path;
1625         int error;
1626
1627         error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1628         if (error)
1629                 return (error);
1630 #ifdef DEBUG
1631         if (ldebug(lchown))
1632                 kprintf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid);
1633 #endif
1634         get_mplock();
1635         error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
1636         if (error == 0)
1637                 error = kern_chown(&nd, args->uid, args->gid);
1638         nlookup_done(&nd);
1639         rel_mplock();
1640         linux_free_path(&path);
1641         return(error);
1642 }
1643
1644 int
1645 sys_linux_fchmodat(struct linux_fchmodat_args *args)
1646 {
1647         struct fchmodat_args uap;
1648         int error;
1649
1650         uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1651         uap.path = args->filename;
1652         uap.mode = args->mode;
1653         uap.flags = 0;
1654
1655         error = sys_fchmodat(&uap);
1656
1657         return (error);
1658 }
1659
1660 int
1661 sys_linux_fchownat(struct linux_fchownat_args *args)
1662 {
1663         struct fchownat_args uap;
1664         int error;
1665
1666         if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
1667                 return (EINVAL);
1668
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;
1675
1676         error = sys_fchownat(&uap);
1677
1678         return (error);
1679 }
1680
1681 int
1682 sys_linux_faccessat(struct linux_faccessat_args *args)
1683 {
1684         struct faccessat_args uap;
1685         int error;
1686
1687         uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1688         uap.path = args->filename;
1689         uap.amode = args->mode;
1690         uap.flags = 0;
1691
1692         error = sys_faccessat(&uap);
1693
1694         return error;
1695 }