sbin/hammer: Directly access volume in volume list
[dragonfly.git] / sys / emulation / linux / linux_file.c
blob5e3a16031035a3c57e548c3bdb790471572b9e89
1 /*-
2 * Copyright (c) 1994-1995 Søren Schmidt
3 * All rights reserved.
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
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * $FreeBSD: src/sys/compat/linux/linux_file.c,v 1.41.2.6 2003/01/06 09:19:43 fjoe Exp $
31 #include "opt_compat.h"
33 #include <sys/param.h>
34 #include <sys/systm.h>
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>
51 #include <vfs/ufs/quota.h>
52 #include <vfs/ufs/ufsmount.h>
54 #include <sys/file2.h>
55 #include <sys/mplock2.h>
57 #include <arch_linux/linux.h>
58 #include <arch_linux/linux_proto.h>
59 #include "linux_util.h"
62 * MPALMOSTSAFE
64 int
65 sys_linux_creat(struct linux_creat_args *args)
67 struct nlookupdata nd;
68 char *path;
69 int error;
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);
83 linux_free_path(&path);
84 return(error);
88 * MPALMOSTSAFE
90 static int
91 linux_open_common(int dfd, char *lpath, int lflags, int mode, int *iresult)
93 struct thread *td = curthread;
94 struct proc *p = td->td_proc;
95 struct nlookupdata nd;
96 struct file *fp;
97 char *path;
98 int error, flags;
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);
107 if (error)
108 return (error);
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;
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);
140 nlookup_done_at(&nd, fp);
142 if (error == 0 && !(flags & O_NOCTTY) &&
143 SESS_LEADER(p) && !(p->p_flags & P_CONTROLT)) {
144 struct file *fp;
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);
152 fdrop(fp);
156 if (error == 0 && lflags & LINUX_O_DIRECTORY) {
157 struct file *fp;
158 struct vnode *vp;
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);
167 if (error)
168 kern_close(*iresult);
172 linux_free_path(&path);
173 return error;
177 sys_linux_open(struct linux_open_args *args)
179 int error;
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
187 error = linux_open_common(AT_FDCWD, args->path, args->flags,
188 args->mode, &args->sysmsg_iresult);
190 #ifdef DEBUG
191 if (ldebug(open))
192 kprintf(LMSG("open returns error %d"), error);
193 #endif
194 return error;
198 sys_linux_openat(struct linux_openat_args *args)
200 int error;
201 int dfd;
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
209 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
211 error = linux_open_common(dfd, args->path, args->flags,
212 args->mode, &args->sysmsg_iresult);
214 #ifdef DEBUG
215 if (ldebug(openat))
216 kprintf(LMSG("openat returns error %d"), error);
217 #endif
218 return error;
222 * MPSAFE
225 sys_linux_lseek(struct linux_lseek_args *args)
227 int error;
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);
237 return error;
241 * MPSAFE
244 sys_linux_llseek(struct linux_llseek_args *args)
246 int error;
247 off_t off, res;
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);
256 error = kern_lseek(args->fd, off, args->whence, &res);
258 if (error == 0)
259 error = copyout(&res, args->res, sizeof(res));
260 return (error);
264 * MPSAFE
267 sys_linux_readdir(struct linux_readdir_args *args)
269 struct linux_getdents_args lda;
270 int error;
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);
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...
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];
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];
305 #define LINUX_RECLEN(de,namlen) \
306 ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
308 #define LINUX_DIRBLKSIZ 512
311 * MPALMOSTSAFE
313 static int
314 getdents_common(struct linux_getdents64_args *args, int is64bit)
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;
338 if ((error = holdvnode(p->p_fd, args->fd, &fp)) != 0)
339 return (error);
341 get_mplock();
342 if ((fp->f_flag & FREAD) == 0) {
343 error = EBADF;
344 goto done;
347 vp = (struct vnode *) fp->f_data;
348 if (vp->v_type != VDIR) {
349 error = EINVAL;
350 goto done;
353 if ((error = VOP_GETATTR(vp, &va)) != 0)
354 goto done;
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;
363 nbytes = sizeof(linux_dirent);
364 justone = 1;
365 } else {
366 justone = 0;
368 if ((ssize_t)nbytes < 0)
369 nbytes = 0;
371 off = fp->f_offset;
373 buflen = max(LINUX_DIRBLKSIZ, nbytes);
374 buflen = min(buflen, MAXBSIZE);
375 buf = kmalloc(buflen, M_TEMP, M_WAITOK);
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;
388 if (cookies) {
389 kfree(cookies, M_TEMP);
390 cookies = NULL;
393 eofflag = 0;
394 ncookies = 0;
395 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
396 &cookies)))
397 goto out;
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;
407 if (cookies) {
409 * When using cookies, the vfs has the option of reading from
410 * a different offset than that supplied (UFS truncates the
411 * offset to a block boundary to make sure that it never reads
412 * partway through a directory entry, even if the directory
413 * has been compacted).
415 while (len > 0 && ncookies > 0 && *cookiep < off) {
416 bdp = (struct dirent *) inp;
417 len -= _DIRENT_DIRSIZ(bdp);
418 inp += _DIRENT_DIRSIZ(bdp);
419 cookiep++;
420 ncookies--;
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;
434 if (bdp->d_ino == 0) {
435 inp += reclen;
436 if (cookiep) {
437 off = *cookiep++;
438 ++off;
439 ncookies--;
440 } else {
441 off += reclen;
443 len -= reclen;
444 continue;
447 linuxreclen = (is64bit)
448 ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen)
449 : LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
451 if (reclen > len || resid < linuxreclen) {
452 outp++;
453 break;
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);
488 if (error)
489 goto out;
491 inp += reclen;
492 if (cookiep) {
493 off = *cookiep++;
494 ++off;
495 ncookies--;
496 } else {
497 off += reclen;
500 outp += linuxreclen;
501 resid -= linuxreclen;
502 len -= reclen;
503 if (justone)
504 break;
507 if (outp == (caddr_t)args->dirent && eofflag == 0)
508 goto again;
510 fp->f_offset = off;
511 if (justone)
512 nbytes = resid + linuxreclen;
514 eof:
515 args->sysmsg_iresult = (int)(nbytes - resid);
517 out:
518 if (cookies)
519 kfree(cookies, M_TEMP);
521 kfree(buf, M_TEMP);
522 done:
523 rel_mplock();
524 fdrop(fp);
525 return (error);
529 * MPSAFE
532 sys_linux_getdents(struct linux_getdents_args *args)
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));
542 * MPSAFE
545 sys_linux_getdents64(struct linux_getdents64_args *args)
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));
555 * These exist mainly for hooks for doing /compat/linux translation.
557 * MPALMOSTSAFE
560 sys_linux_access(struct linux_access_args *args)
562 struct nlookupdata nd;
563 char *path;
564 int error;
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);
584 * MPALMOSTSAFE
587 sys_linux_unlink(struct linux_unlink_args *args)
589 struct nlookupdata nd;
590 char *path;
591 int error;
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);
611 sys_linux_unlinkat(struct linux_unlinkat_args *args)
613 struct nlookupdata nd;
614 struct file *fp;
615 char *path;
616 int dfd, error;
618 if (args->flag & ~LINUX_AT_REMOVEDIR)
619 return (EINVAL);
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);
626 #ifdef DEBUG
627 if (ldebug(unlink))
628 kprintf(ARGS(unlink, "%s"), path);
629 #endif
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);
640 nlookup_done_at(&nd, fp);
641 rel_mplock();
642 linux_free_path(&path);
643 return(error);
647 * MPALMOSTSAFE
650 sys_linux_chdir(struct linux_chdir_args *args)
652 struct nlookupdata nd;
653 char *path;
654 int error;
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);
669 rel_mplock();
670 linux_free_path(&path);
671 return(error);
675 * MPALMOSTSAFE
678 sys_linux_chmod(struct linux_chmod_args *args)
680 struct nlookupdata nd;
681 char *path;
682 int error;
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);
702 * MPALMOSTSAFE
705 sys_linux_mkdir(struct linux_mkdir_args *args)
707 struct nlookupdata nd;
708 char *path;
709 int error;
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();
725 linux_free_path(&path);
726 return(error);
730 sys_linux_mkdirat(struct linux_mkdirat_args *args)
732 struct nlookupdata nd;
733 struct file *fp;
734 char *path;
735 int dfd, error;
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();
752 linux_free_path(&path);
753 return(error);
757 * MPALMOSTSAFE
760 sys_linux_rmdir(struct linux_rmdir_args *args)
762 struct nlookupdata nd;
763 char *path;
764 int error;
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);
784 * MPALMOSTSAFE
787 sys_linux_rename(struct linux_rename_args *args)
789 struct nlookupdata fromnd, tond;
790 char *from, *to;
791 int error;
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);
801 #ifdef DEBUG
802 if (ldebug(rename))
803 kprintf(ARGS(rename, "%s, %s"), from, to);
804 #endif
805 get_mplock();
806 do {
807 error = nlookup_init(&fromnd, from, UIO_SYSSPACE, 0);
808 if (error == 0) {
809 error = nlookup_init(&tond, to, UIO_SYSSPACE, 0);
810 if (error == 0)
811 error = kern_rename(&fromnd, &tond);
812 nlookup_done(&tond);
814 nlookup_done(&fromnd);
815 } while (error == EAGAIN);
816 rel_mplock();
817 linux_free_path(&from);
818 linux_free_path(&to);
819 return(error);
823 sys_linux_renameat(struct linux_renameat_args *args)
825 struct nlookupdata fromnd, tond;
826 struct file *fp, *fp2;
827 char *from, *to;
828 int olddfd, newdfd,error;
830 error = linux_copyin_path(args->from, &from, LINUX_PATH_EXISTS);
831 if (error)
832 return (error);
833 error = linux_copyin_path(args->to, &to, LINUX_PATH_CREATE);
834 if (error) {
835 linux_free_path(&from);
836 return (error);
838 #ifdef DEBUG
839 if (ldebug(rename))
840 kprintf(ARGS(rename, "%s, %s"), from, to);
841 #endif
842 olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
843 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
844 get_mplock();
845 error = nlookup_init_at(&fromnd, &fp, olddfd, from, UIO_SYSSPACE, 0);
846 if (error == 0) {
847 error = nlookup_init_at(&tond, &fp2, newdfd, to, UIO_SYSSPACE, 0);
848 if (error == 0)
849 error = kern_rename(&fromnd, &tond);
850 nlookup_done_at(&tond, fp2);
852 nlookup_done_at(&fromnd, fp);
853 rel_mplock();
854 linux_free_path(&from);
855 linux_free_path(&to);
856 return(error);
860 * MPALMOSTSAFE
863 sys_linux_symlink(struct linux_symlink_args *args)
865 struct thread *td = curthread;
866 struct nlookupdata nd;
867 char *path, *link;
868 int error;
869 int mode;
871 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
872 if (error)
873 return (error);
874 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
875 if (error) {
876 linux_free_path(&path);
877 return (error);
879 #ifdef DEBUG
880 if (ldebug(symlink))
881 kprintf(ARGS(symlink, "%s, %s"), path, link);
882 #endif
883 get_mplock();
884 error = nlookup_init(&nd, link, UIO_SYSSPACE, 0);
885 if (error == 0) {
886 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
887 error = kern_symlink(&nd, path, mode);
889 nlookup_done(&nd);
890 rel_mplock();
891 linux_free_path(&path);
892 linux_free_path(&link);
893 return(error);
897 sys_linux_symlinkat(struct linux_symlinkat_args *args)
899 struct thread *td = curthread;
900 struct nlookupdata nd;
901 struct file *fp;
902 char *path, *link;
903 int error;
904 int newdfd, mode;
906 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
907 if (error)
908 return (error);
909 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
910 if (error) {
911 linux_free_path(&path);
912 return (error);
914 #ifdef DEBUG
915 if (ldebug(symlink))
916 kprintf(ARGS(symlink, "%s, %s"), path, link);
917 #endif
918 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
919 get_mplock();
920 error = nlookup_init_at(&nd, &fp, newdfd, link, UIO_SYSSPACE, 0);
921 if (error == 0) {
922 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
923 error = kern_symlink(&nd, path, mode);
925 nlookup_done_at(&nd, fp);
926 rel_mplock();
927 linux_free_path(&path);
928 linux_free_path(&link);
929 return(error);
933 * MPALMOSTSAFE
936 sys_linux_readlink(struct linux_readlink_args *args)
938 struct nlookupdata nd;
939 char *path;
940 int error;
942 error = linux_copyin_path(args->name, &path, LINUX_PATH_EXISTS);
943 if (error)
944 return (error);
945 #ifdef DEBUG
946 if (ldebug(readlink))
947 kprintf(ARGS(readlink, "%s, %p, %d"), path, (void *)args->buf,
948 args->count);
949 #endif
950 get_mplock();
951 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
952 if (error == 0) {
953 error = kern_readlink(&nd, args->buf, args->count,
954 &args->sysmsg_iresult);
956 nlookup_done(&nd);
957 rel_mplock();
958 linux_free_path(&path);
959 return(error);
963 sys_linux_readlinkat(struct linux_readlinkat_args *args)
965 struct nlookupdata nd;
966 struct file *fp;
967 char *path;
968 int dfd, error;
970 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
971 if (error)
972 return (error);
973 #ifdef DEBUG
974 if (ldebug(readlink))
975 kprintf(ARGS(readlink, "%s, %p, %d"), path, (void *)args->buf,
976 args->count);
977 #endif
978 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
979 get_mplock();
980 error = nlookup_init_at(&nd, &fp, dfd, path, UIO_SYSSPACE, 0);
981 if (error == 0) {
982 error = kern_readlink(&nd, args->buf, args->count,
983 &args->sysmsg_iresult);
985 nlookup_done_at(&nd, fp);
986 rel_mplock();
987 linux_free_path(&path);
988 return(error);
992 * MPALMOSTSAFE
995 sys_linux_truncate(struct linux_truncate_args *args)
997 struct nlookupdata nd;
998 char *path;
999 int error;
1001 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1002 if (error)
1003 return (error);
1004 #ifdef DEBUG
1005 if (ldebug(truncate))
1006 kprintf(ARGS(truncate, "%s, %ld"), path,
1007 (long)args->length);
1008 #endif
1009 get_mplock();
1010 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1011 if (error == 0)
1012 error = kern_truncate(&nd, args->length);
1013 nlookup_done(&nd);
1014 rel_mplock();
1015 linux_free_path(&path);
1016 return(error);
1020 * MPALMOSTSAFE
1023 sys_linux_truncate64(struct linux_truncate64_args *args)
1025 struct nlookupdata nd;
1026 char *path;
1027 int error;
1029 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1030 if (error)
1031 return (error);
1032 #ifdef DEBUG
1033 if (ldebug(truncate64))
1034 kprintf(ARGS(truncate64, "%s, %lld"), path,
1035 (off_t)args->length);
1036 #endif
1037 get_mplock();
1038 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1039 if (error == 0)
1040 error = kern_truncate(&nd, args->length);
1041 nlookup_done(&nd);
1042 rel_mplock();
1043 linux_free_path(&path);
1044 return error;
1048 * MPALMOSTSAFE
1051 sys_linux_ftruncate(struct linux_ftruncate_args *args)
1053 int error;
1055 #ifdef DEBUG
1056 if (ldebug(ftruncate))
1057 kprintf(ARGS(ftruncate, "%d, %ld"), args->fd,
1058 (long)args->length);
1059 #endif
1060 get_mplock();
1061 error = kern_ftruncate(args->fd, args->length);
1062 rel_mplock();
1064 return error;
1068 * MPALMOSTSAFE
1071 sys_linux_ftruncate64(struct linux_ftruncate64_args *args)
1073 int error;
1075 #ifdef DEBUG
1076 if (ldebug(ftruncate))
1077 kprintf(ARGS(ftruncate64, "%d, %lld"), args->fd,
1078 (off_t)args->length);
1079 #endif
1080 get_mplock();
1081 error = kern_ftruncate(args->fd, args->length);
1082 rel_mplock();
1084 return error;
1088 * MPALMOSTSAFE
1091 sys_linux_link(struct linux_link_args *args)
1093 struct nlookupdata nd, linknd;
1094 char *path, *link;
1095 int error;
1097 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1098 if (error)
1099 return (error);
1100 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
1101 if (error) {
1102 linux_free_path(&path);
1103 return (error);
1105 #ifdef DEBUG
1106 if (ldebug(link))
1107 kprintf(ARGS(link, "%s, %s"), path, link);
1108 #endif
1109 get_mplock();
1110 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1111 if (error == 0) {
1112 error = nlookup_init(&linknd, link, UIO_SYSSPACE, 0);
1113 if (error == 0)
1114 error = kern_link(&nd, &linknd);
1115 nlookup_done(&linknd);
1117 nlookup_done(&nd);
1118 rel_mplock();
1119 linux_free_path(&path);
1120 linux_free_path(&link);
1121 return(error);
1125 sys_linux_linkat(struct linux_linkat_args *args)
1127 struct nlookupdata nd, linknd;
1128 struct file *fp, *fp2;
1129 char *path, *link;
1130 int olddfd, newdfd, error;
1132 if (args->flags != 0)
1133 return (EINVAL);
1135 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1136 if (error)
1137 return (error);
1138 error = linux_copyin_path(args->to, &link, LINUX_PATH_CREATE);
1139 if (error) {
1140 linux_free_path(&path);
1141 return (error);
1143 #ifdef DEBUG
1144 if (ldebug(link))
1145 kprintf(ARGS(link, "%s, %s"), path, link);
1146 #endif
1147 olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
1148 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
1149 get_mplock();
1150 error = nlookup_init_at(&nd, &fp, olddfd, path, UIO_SYSSPACE, NLC_FOLLOW);
1151 if (error == 0) {
1152 error = nlookup_init_at(&linknd, &fp2, newdfd, link, UIO_SYSSPACE, 0);
1153 if (error == 0)
1154 error = kern_link(&nd, &linknd);
1155 nlookup_done_at(&linknd, fp2);
1157 nlookup_done_at(&nd, fp);
1158 rel_mplock();
1159 linux_free_path(&path);
1160 linux_free_path(&link);
1161 return(error);
1165 * MPSAFE
1168 sys_linux_fdatasync(struct linux_fdatasync_args *uap)
1170 struct fsync_args bsd;
1171 int error;
1173 bsd.fd = uap->fd;
1174 bsd.sysmsg_iresult = 0;
1176 error = sys_fsync(&bsd);
1177 uap->sysmsg_iresult = bsd.sysmsg_iresult;
1178 return(error);
1182 * MPSAFE
1185 sys_linux_pread(struct linux_pread_args *uap)
1187 struct thread *td = curthread;
1188 struct uio auio;
1189 struct iovec aiov;
1190 int error;
1192 aiov.iov_base = uap->buf;
1193 aiov.iov_len = uap->nbyte;
1194 auio.uio_iov = &aiov;
1195 auio.uio_iovcnt = 1;
1196 auio.uio_offset = uap->offset;
1197 auio.uio_resid = uap->nbyte;
1198 auio.uio_rw = UIO_READ;
1199 auio.uio_segflg = UIO_USERSPACE;
1200 auio.uio_td = td;
1202 if ((ssize_t)auio.uio_resid < 0) {
1203 error = EINVAL;
1204 } else {
1205 error = kern_preadv(uap->fd, &auio, O_FOFFSET,
1206 &uap->sysmsg_szresult);
1208 return(error);
1212 * MPSAFE
1215 sys_linux_pwrite(struct linux_pwrite_args *uap)
1217 struct thread *td = curthread;
1218 struct uio auio;
1219 struct iovec aiov;
1220 int error;
1222 aiov.iov_base = uap->buf;
1223 aiov.iov_len = uap->nbyte;
1224 auio.uio_iov = &aiov;
1225 auio.uio_iovcnt = 1;
1226 auio.uio_offset = uap->offset;
1227 auio.uio_resid = uap->nbyte;
1228 auio.uio_rw = UIO_WRITE;
1229 auio.uio_segflg = UIO_USERSPACE;
1230 auio.uio_td = td;
1232 if ((ssize_t)auio.uio_resid < 0) {
1233 error = EINVAL;
1234 } else {
1235 error = kern_pwritev(uap->fd, &auio, O_FOFFSET,
1236 &uap->sysmsg_szresult);
1238 return(error);
1242 * MPSAFE
1245 sys_linux_oldumount(struct linux_oldumount_args *args)
1247 struct linux_umount_args args2;
1248 int error;
1250 args2.path = args->path;
1251 args2.flags = 0;
1252 args2.sysmsg_iresult = 0;
1253 error = sys_linux_umount(&args2);
1254 args->sysmsg_iresult = args2.sysmsg_iresult;
1255 return(error);
1259 * MPSAFE
1262 sys_linux_umount(struct linux_umount_args *args)
1264 struct unmount_args bsd;
1265 int error;
1267 bsd.path = args->path;
1268 bsd.flags = args->flags; /* XXX correct? */
1269 bsd.sysmsg_iresult = 0;
1271 error = sys_unmount(&bsd);
1272 args->sysmsg_iresult = bsd.sysmsg_iresult;
1273 return(error);
1277 * fcntl family of syscalls
1279 struct l_flock {
1280 l_short l_type;
1281 l_short l_whence;
1282 l_off_t l_start;
1283 l_off_t l_len;
1284 l_pid_t l_pid;
1288 * MPSAFE
1290 static void
1291 linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
1293 switch (linux_flock->l_type) {
1294 case LINUX_F_RDLCK:
1295 bsd_flock->l_type = F_RDLCK;
1296 break;
1297 case LINUX_F_WRLCK:
1298 bsd_flock->l_type = F_WRLCK;
1299 break;
1300 case LINUX_F_UNLCK:
1301 bsd_flock->l_type = F_UNLCK;
1302 break;
1303 default:
1304 bsd_flock->l_type = -1;
1305 break;
1307 bsd_flock->l_whence = linux_flock->l_whence;
1308 bsd_flock->l_start = (off_t)linux_flock->l_start;
1309 bsd_flock->l_len = (off_t)linux_flock->l_len;
1310 bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1314 * MPSAFE
1316 static void
1317 bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
1319 switch (bsd_flock->l_type) {
1320 case F_RDLCK:
1321 linux_flock->l_type = LINUX_F_RDLCK;
1322 break;
1323 case F_WRLCK:
1324 linux_flock->l_type = LINUX_F_WRLCK;
1325 break;
1326 case F_UNLCK:
1327 linux_flock->l_type = LINUX_F_UNLCK;
1328 break;
1330 linux_flock->l_whence = bsd_flock->l_whence;
1331 linux_flock->l_start = (l_off_t)bsd_flock->l_start;
1332 linux_flock->l_len = (l_off_t)bsd_flock->l_len;
1333 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
1336 #if defined(__i386__)
1337 struct l_flock64 {
1338 l_short l_type;
1339 l_short l_whence;
1340 l_loff_t l_start;
1341 l_loff_t l_len;
1342 l_pid_t l_pid;
1346 * MPSAFE
1348 static void
1349 linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
1351 switch (linux_flock->l_type) {
1352 case LINUX_F_RDLCK:
1353 bsd_flock->l_type = F_RDLCK;
1354 break;
1355 case LINUX_F_WRLCK:
1356 bsd_flock->l_type = F_WRLCK;
1357 break;
1358 case LINUX_F_UNLCK:
1359 bsd_flock->l_type = F_UNLCK;
1360 break;
1361 default:
1362 bsd_flock->l_type = -1;
1363 break;
1365 bsd_flock->l_whence = linux_flock->l_whence;
1366 bsd_flock->l_start = (off_t)linux_flock->l_start;
1367 bsd_flock->l_len = (off_t)linux_flock->l_len;
1368 bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1372 * MPSAFE
1374 static void
1375 bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
1377 switch (bsd_flock->l_type) {
1378 case F_RDLCK:
1379 linux_flock->l_type = LINUX_F_RDLCK;
1380 break;
1381 case F_WRLCK:
1382 linux_flock->l_type = LINUX_F_WRLCK;
1383 break;
1384 case F_UNLCK:
1385 linux_flock->l_type = LINUX_F_UNLCK;
1386 break;
1388 linux_flock->l_whence = bsd_flock->l_whence;
1389 linux_flock->l_start = (l_loff_t)bsd_flock->l_start;
1390 linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
1391 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
1393 #endif /* __i386__ */
1396 * MPSAFE
1398 static int
1399 linux_fcntl_common(struct linux_fcntl64_args *args)
1401 struct thread *td = curthread;
1402 struct l_flock linux_flock;
1403 struct file *fp;
1404 union fcntl_dat dat;
1405 int error, cmd;
1407 switch (args->cmd) {
1408 case LINUX_F_DUPFD:
1409 cmd = F_DUPFD;
1410 dat.fc_fd = args->arg;
1411 break;
1412 case LINUX_F_GETFD:
1413 cmd = F_GETFD;
1414 break;
1415 case LINUX_F_SETFD:
1416 cmd = F_SETFD;
1417 dat.fc_cloexec = args->arg;
1418 break;
1419 case LINUX_F_GETFL:
1420 cmd = F_GETFL;
1421 break;
1422 case LINUX_F_SETFL:
1423 cmd = F_SETFL;
1424 dat.fc_flags = 0;
1425 if (args->arg & LINUX_O_NDELAY)
1426 dat.fc_flags |= O_NONBLOCK;
1427 if (args->arg & LINUX_O_APPEND)
1428 dat.fc_flags |= O_APPEND;
1429 if (args->arg & LINUX_O_SYNC)
1430 dat.fc_flags |= O_FSYNC;
1431 if (args->arg & LINUX_FASYNC)
1432 dat.fc_flags |= O_ASYNC;
1433 break;
1434 case LINUX_F_GETLK:
1435 case LINUX_F_SETLK:
1436 case LINUX_F_SETLKW:
1437 cmd = F_GETLK;
1438 error = copyin((caddr_t)args->arg, &linux_flock,
1439 sizeof(linux_flock));
1440 if (error)
1441 return (error);
1442 linux_to_bsd_flock(&linux_flock, &dat.fc_flock);
1443 break;
1444 case LINUX_F_GETOWN:
1445 cmd = F_GETOWN;
1446 break;
1447 case LINUX_F_SETOWN:
1449 * XXX some Linux applications depend on F_SETOWN having no
1450 * significant effect for pipes (SIGIO is not delivered for
1451 * pipes under Linux-2.2.35 at least).
1453 fp = holdfp(td->td_proc->p_fd, args->fd, -1);
1454 if (fp == NULL)
1455 return (EBADF);
1456 if (fp->f_type == DTYPE_PIPE) {
1457 fdrop(fp);
1458 return (EINVAL);
1460 fdrop(fp);
1461 cmd = F_SETOWN;
1462 dat.fc_owner = args->arg;
1463 break;
1464 default:
1465 return (EINVAL);
1468 /* MPSAFE */
1469 error = kern_fcntl(args->fd, cmd, &dat, td->td_ucred);
1471 if (error == 0) {
1472 switch (args->cmd) {
1473 case LINUX_F_DUPFD:
1474 args->sysmsg_iresult = dat.fc_fd;
1475 break;
1476 case LINUX_F_GETFD:
1477 args->sysmsg_iresult = dat.fc_cloexec;
1478 break;
1479 case LINUX_F_SETFD:
1480 break;
1481 case LINUX_F_GETFL:
1482 args->sysmsg_iresult = 0;
1483 if (dat.fc_flags & O_RDONLY)
1484 args->sysmsg_iresult |= LINUX_O_RDONLY;
1485 if (dat.fc_flags & O_WRONLY)
1486 args->sysmsg_iresult |= LINUX_O_WRONLY;
1487 if (dat.fc_flags & O_RDWR)
1488 args->sysmsg_iresult |= LINUX_O_RDWR;
1489 if (dat.fc_flags & O_NDELAY)
1490 args->sysmsg_iresult |= LINUX_O_NONBLOCK;
1491 if (dat.fc_flags & O_APPEND)
1492 args->sysmsg_iresult |= LINUX_O_APPEND;
1493 if (dat.fc_flags & O_FSYNC)
1494 args->sysmsg_iresult |= LINUX_O_SYNC;
1495 if (dat.fc_flags & O_ASYNC)
1496 args->sysmsg_iresult |= LINUX_FASYNC;
1497 break;
1498 case LINUX_F_GETLK:
1499 bsd_to_linux_flock(&dat.fc_flock, &linux_flock);
1500 error = copyout(&linux_flock, (caddr_t)args->arg,
1501 sizeof(linux_flock));
1502 break;
1503 case LINUX_F_SETLK:
1504 case LINUX_F_SETLKW:
1505 break;
1506 case LINUX_F_GETOWN:
1507 args->sysmsg_iresult = dat.fc_owner;
1508 break;
1509 case LINUX_F_SETOWN:
1510 break;
1514 return(error);
1518 * MPSAFE
1521 sys_linux_fcntl(struct linux_fcntl_args *args)
1523 struct linux_fcntl64_args args64;
1524 int error;
1526 #ifdef DEBUG
1527 if (ldebug(fcntl))
1528 kprintf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
1529 #endif
1531 args64.fd = args->fd;
1532 args64.cmd = args->cmd;
1533 args64.arg = args->arg;
1534 args64.sysmsg_iresult = 0;
1535 error = linux_fcntl_common(&args64);
1536 args->sysmsg_iresult = args64.sysmsg_iresult;
1537 return(error);
1540 #if defined(__i386__)
1542 * MPSAFE
1545 sys_linux_fcntl64(struct linux_fcntl64_args *args)
1547 struct thread *td = curthread;
1548 struct l_flock64 linux_flock;
1549 union fcntl_dat dat;
1550 int error, cmd = 0;
1552 #ifdef DEBUG
1553 if (ldebug(fcntl64))
1554 kprintf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd);
1555 #endif
1556 if (args->cmd == LINUX_F_GETLK64 || args->cmd == LINUX_F_SETLK64 ||
1557 args->cmd == LINUX_F_SETLKW64) {
1558 switch (args->cmd) {
1559 case LINUX_F_GETLK64:
1560 cmd = F_GETLK;
1561 break;
1562 case LINUX_F_SETLK64:
1563 cmd = F_SETLK;
1564 break;
1565 case LINUX_F_SETLKW64:
1566 cmd = F_SETLKW;
1567 break;
1570 error = copyin((caddr_t)args->arg, &linux_flock,
1571 sizeof(linux_flock));
1572 if (error)
1573 return (error);
1574 linux_to_bsd_flock64(&linux_flock, &dat.fc_flock);
1576 /* MPSAFE */
1577 error = kern_fcntl(args->fd, cmd, &dat, td->td_ucred);
1579 if (error == 0 && args->cmd == LINUX_F_GETLK64) {
1580 bsd_to_linux_flock64(&dat.fc_flock, &linux_flock);
1581 error = copyout(&linux_flock, (caddr_t)args->arg,
1582 sizeof(linux_flock));
1584 } else {
1585 error = linux_fcntl_common(args);
1588 return (error);
1590 #endif /* __i386__ */
1593 * MPALMOSTSAFE
1596 sys_linux_chown(struct linux_chown_args *args)
1598 struct nlookupdata nd;
1599 char *path;
1600 int error;
1602 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1603 if (error)
1604 return (error);
1605 #ifdef DEBUG
1606 if (ldebug(chown))
1607 kprintf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid);
1608 #endif
1609 get_mplock();
1610 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1611 if (error == 0)
1612 error = kern_chown(&nd, args->uid, args->gid);
1613 nlookup_done(&nd);
1614 rel_mplock();
1615 linux_free_path(&path);
1616 return(error);
1620 * MPALMOSTSAFE
1623 sys_linux_lchown(struct linux_lchown_args *args)
1625 struct nlookupdata nd;
1626 char *path;
1627 int error;
1629 error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS);
1630 if (error)
1631 return (error);
1632 #ifdef DEBUG
1633 if (ldebug(lchown))
1634 kprintf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid);
1635 #endif
1636 get_mplock();
1637 error = nlookup_init(&nd, path, UIO_SYSSPACE, 0);
1638 if (error == 0)
1639 error = kern_chown(&nd, args->uid, args->gid);
1640 nlookup_done(&nd);
1641 rel_mplock();
1642 linux_free_path(&path);
1643 return(error);
1647 sys_linux_fchmodat(struct linux_fchmodat_args *args)
1649 struct fchmodat_args uap;
1650 int error;
1652 uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1653 uap.path = args->filename;
1654 uap.mode = args->mode;
1655 uap.flags = 0;
1657 error = sys_fchmodat(&uap);
1659 return (error);
1663 sys_linux_fchownat(struct linux_fchownat_args *args)
1665 struct fchownat_args uap;
1666 int error;
1668 if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
1669 return (EINVAL);
1671 uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1672 uap.path = args->filename;
1673 uap.uid = args->uid;
1674 uap.gid = args->gid;
1675 uap.flags = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 :
1676 AT_SYMLINK_NOFOLLOW;
1678 error = sys_fchownat(&uap);
1680 return (error);
1684 sys_linux_faccessat(struct linux_faccessat_args *args)
1686 struct faccessat_args uap;
1687 int error;
1689 uap.fd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1690 uap.path = args->filename;
1691 uap.amode = args->mode;
1692 uap.flags = 0;
1694 error = sys_faccessat(&uap);
1696 return error;