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