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