Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sys / emulation / linux / linux_file.c
1 /*-
2  * Copyright (c) 1994-1995 Søren Schmidt
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer 
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software 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 $
29  * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.2 2003/06/17 04:28:19 dillon Exp $
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>
40 #include <sys/filedesc.h>
41 #include <sys/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/mount.h>
44 #include <sys/proc.h>
45 #include <sys/sysproto.h>
46 #include <sys/tty.h>
47 #include <sys/vnode.h>
48
49 #include <ufs/ufs/quota.h>
50 #include <ufs/ufs/ufsmount.h>
51
52 #include <machine/../linux/linux.h>
53 #include <machine/../linux/linux_proto.h>
54 #include <compat/linux/linux_util.h>
55
56 #ifndef __alpha__
57 int
58 linux_creat(struct proc *p, struct linux_creat_args *args)
59 {
60     struct open_args /* {
61         char *path;
62         int flags;
63         int mode;
64     } */ bsd_open_args;
65     caddr_t sg;
66
67     sg = stackgap_init();
68     CHECKALTCREAT(p, &sg, args->path);
69
70 #ifdef DEBUG
71         if (ldebug(creat))
72                 printf(ARGS(creat, "%s, %d"), args->path, args->mode);
73 #endif
74     bsd_open_args.path = args->path;
75     bsd_open_args.mode = args->mode;
76     bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
77     return open(p, &bsd_open_args);
78 }
79 #endif /*!__alpha__*/
80
81 int
82 linux_open(struct proc *p, struct linux_open_args *args)
83 {
84     struct open_args /* {
85         char *path;
86         int flags;
87         int mode;
88     } */ bsd_open_args;
89     int error;
90     caddr_t sg;
91
92     sg = stackgap_init();
93     
94     if (args->flags & LINUX_O_CREAT)
95         CHECKALTCREAT(p, &sg, args->path);
96     else
97         CHECKALTEXIST(p, &sg, args->path);
98
99 #ifdef DEBUG
100         if (ldebug(open))
101                 printf(ARGS(open, "%s, 0x%x, 0x%x"),
102                     args->path, args->flags, args->mode);
103 #endif
104     bsd_open_args.flags = 0;
105     if (args->flags & LINUX_O_RDONLY)
106         bsd_open_args.flags |= O_RDONLY;
107     if (args->flags & LINUX_O_WRONLY) 
108         bsd_open_args.flags |= O_WRONLY;
109     if (args->flags & LINUX_O_RDWR)
110         bsd_open_args.flags |= O_RDWR;
111     if (args->flags & LINUX_O_NDELAY)
112         bsd_open_args.flags |= O_NONBLOCK;
113     if (args->flags & LINUX_O_APPEND)
114         bsd_open_args.flags |= O_APPEND;
115     if (args->flags & LINUX_O_SYNC)
116         bsd_open_args.flags |= O_FSYNC;
117     if (args->flags & LINUX_O_NONBLOCK)
118         bsd_open_args.flags |= O_NONBLOCK;
119     if (args->flags & LINUX_FASYNC)
120         bsd_open_args.flags |= O_ASYNC;
121     if (args->flags & LINUX_O_CREAT)
122         bsd_open_args.flags |= O_CREAT;
123     if (args->flags & LINUX_O_TRUNC)
124         bsd_open_args.flags |= O_TRUNC;
125     if (args->flags & LINUX_O_EXCL)
126         bsd_open_args.flags |= O_EXCL;
127     if (args->flags & LINUX_O_NOCTTY)
128         bsd_open_args.flags |= O_NOCTTY;
129     bsd_open_args.path = args->path;
130     bsd_open_args.mode = args->mode;
131
132     error = open(p, &bsd_open_args);
133     if (!error && !(bsd_open_args.flags & O_NOCTTY) && 
134         SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
135         struct filedesc *fdp = p->p_fd;
136         struct file *fp = fdp->fd_ofiles[p->p_retval[0]];
137
138         if (fp->f_type == DTYPE_VNODE)
139             fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, p);
140     }
141 #ifdef DEBUG
142         if (ldebug(open))
143                 printf(LMSG("open returns error %d"), error);
144 #endif
145     return error;
146 }
147
148 int
149 linux_lseek(struct proc *p, struct linux_lseek_args *args)
150 {
151
152     struct lseek_args /* {
153         int fd;
154         int pad;
155         off_t offset;
156         int whence;
157     } */ tmp_args;
158     int error;
159
160 #ifdef DEBUG
161         if (ldebug(lseek))
162                 printf(ARGS(lseek, "%d, %ld, %d"),
163                     args->fdes, (long)args->off, args->whence);
164 #endif
165     tmp_args.fd = args->fdes;
166     tmp_args.offset = (off_t)args->off;
167     tmp_args.whence = args->whence;
168     error = lseek(p, &tmp_args);
169     return error;
170 }
171
172 #ifndef __alpha__
173 int
174 linux_llseek(struct proc *p, struct linux_llseek_args *args)
175 {
176         struct lseek_args bsd_args;
177         int error;
178         off_t off;
179
180 #ifdef DEBUG
181         if (ldebug(llseek))
182                 printf(ARGS(llseek, "%d, %d:%d, %d"),
183                     args->fd, args->ohigh, args->olow, args->whence);
184 #endif
185         off = (args->olow) | (((off_t) args->ohigh) << 32);
186
187         bsd_args.fd = args->fd;
188         bsd_args.offset = off;
189         bsd_args.whence = args->whence;
190
191         if ((error = lseek(p, &bsd_args)))
192                 return error;
193
194         if ((error = copyout(p->p_retval, (caddr_t)args->res, sizeof (off_t))))
195                 return error;
196
197         p->p_retval[0] = 0;
198         return 0;
199 }
200 #endif /*!__alpha__*/
201
202 #ifndef __alpha__
203 int
204 linux_readdir(struct proc *p, struct linux_readdir_args *args)
205 {
206         struct linux_getdents_args lda;
207
208         lda.fd = args->fd;
209         lda.dent = args->dent;
210         lda.count = 1;
211         return linux_getdents(p, &lda);
212 }
213 #endif /*!__alpha__*/
214
215 /*
216  * Note that linux_getdents(2) and linux_getdents64(2) have the same
217  * arguments. They only differ in the definition of struct dirent they
218  * operate on. We use this to common the code, with the exception of
219  * accessing struct dirent. Note that linux_readdir(2) is implemented
220  * by means of linux_getdents(2). In this case we never operate on
221  * struct dirent64 and thus don't need to handle it...
222  */
223
224 struct l_dirent {
225         l_long          d_ino;
226         l_off_t         d_off;
227         l_ushort        d_reclen;
228         char            d_name[LINUX_NAME_MAX + 1];
229 };
230
231 struct l_dirent64 {
232         uint64_t        d_ino;
233         int64_t         d_off;
234         l_ushort        d_reclen;
235         u_char          d_type;
236         char            d_name[LINUX_NAME_MAX + 1];
237 };
238
239 #define LINUX_RECLEN(de,namlen) \
240     ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
241
242 #define LINUX_DIRBLKSIZ         512
243
244 static int
245 getdents_common(struct proc *p, struct linux_getdents64_args *args,
246     int is64bit)
247 {
248         register struct dirent *bdp;
249         struct vnode *vp;
250         caddr_t inp, buf;               /* BSD-format */
251         int len, reclen;                /* BSD-format */
252         caddr_t outp;                   /* Linux-format */
253         int resid, linuxreclen=0;       /* Linux-format */
254         struct file *fp;
255         struct uio auio;
256         struct iovec aiov;
257         struct vattr va;
258         off_t off;
259         struct l_dirent linux_dirent;
260         struct l_dirent64 linux_dirent64;
261         int buflen, error, eofflag, nbytes, justone;
262         u_long *cookies = NULL, *cookiep;
263         int ncookies;
264
265         if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0)
266                 return (error);
267
268         if ((fp->f_flag & FREAD) == 0)
269                 return (EBADF);
270
271         vp = (struct vnode *) fp->f_data;
272         if (vp->v_type != VDIR)
273                 return (EINVAL);
274
275         if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
276                 return (error);
277
278         nbytes = args->count;
279         if (nbytes == 1) {
280                 /* readdir(2) case. Always struct dirent. */
281                 if (is64bit)
282                         return (EINVAL);
283                 nbytes = sizeof(linux_dirent);
284                 justone = 1;
285         } else
286                 justone = 0;
287
288         off = fp->f_offset;
289
290         buflen = max(LINUX_DIRBLKSIZ, nbytes);
291         buflen = min(buflen, MAXBSIZE);
292         buf = malloc(buflen, M_TEMP, M_WAITOK);
293         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
294
295 again:
296         aiov.iov_base = buf;
297         aiov.iov_len = buflen;
298         auio.uio_iov = &aiov;
299         auio.uio_iovcnt = 1;
300         auio.uio_rw = UIO_READ;
301         auio.uio_segflg = UIO_SYSSPACE;
302         auio.uio_procp = p;
303         auio.uio_resid = buflen;
304         auio.uio_offset = off;
305
306         if (cookies) {
307                 free(cookies, M_TEMP);
308                 cookies = NULL;
309         }
310
311         if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
312                  &cookies)))
313                 goto out;
314
315         inp = buf;
316         outp = (caddr_t)args->dirent;
317         resid = nbytes;
318         if ((len = buflen - auio.uio_resid) <= 0)
319                 goto eof;
320
321         cookiep = cookies;
322
323         if (cookies) {
324                 /*
325                  * When using cookies, the vfs has the option of reading from
326                  * a different offset than that supplied (UFS truncates the
327                  * offset to a block boundary to make sure that it never reads
328                  * partway through a directory entry, even if the directory
329                  * has been compacted).
330                  */
331                 while (len > 0 && ncookies > 0 && *cookiep <= off) {
332                         bdp = (struct dirent *) inp;
333                         len -= bdp->d_reclen;
334                         inp += bdp->d_reclen;
335                         cookiep++;
336                         ncookies--;
337                 }
338         }
339
340         while (len > 0) {
341                 if (cookiep && ncookies == 0)
342                         break;
343                 bdp = (struct dirent *) inp;
344                 reclen = bdp->d_reclen;
345                 if (reclen & 3) {
346                         error = EFAULT;
347                         goto out;
348                 }
349
350                 if (bdp->d_fileno == 0) {
351                         inp += reclen;
352                         if (cookiep) {
353                                 off = *cookiep++;
354                                 ncookies--;
355                         } else
356                                 off += reclen;
357
358                         len -= reclen;
359                         continue;
360                 }
361
362                 linuxreclen = (is64bit)
363                     ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen)
364                     : LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
365
366                 if (reclen > len || resid < linuxreclen) {
367                         outp++;
368                         break;
369                 }
370
371                 if (justone) {
372                         /* readdir(2) case. */
373                         linux_dirent.d_ino = (l_long)bdp->d_fileno;
374                         linux_dirent.d_off = (l_off_t)linuxreclen;
375                         linux_dirent.d_reclen = (l_ushort)bdp->d_namlen;
376                         strcpy(linux_dirent.d_name, bdp->d_name);
377                         error = copyout(&linux_dirent, outp, linuxreclen);
378                 } else {
379                         if (is64bit) {
380                                 linux_dirent64.d_ino = bdp->d_fileno;
381                                 linux_dirent64.d_off = (cookiep)
382                                     ? (l_off_t)*cookiep
383                                     : (l_off_t)(off + reclen);
384                                 linux_dirent64.d_reclen =
385                                     (l_ushort)linuxreclen;
386                                 linux_dirent64.d_type = bdp->d_type;
387                                 strcpy(linux_dirent64.d_name, bdp->d_name);
388                                 error = copyout(&linux_dirent64, outp,
389                                     linuxreclen);
390                         } else {
391                                 linux_dirent.d_ino = bdp->d_fileno;
392                                 linux_dirent.d_off = (cookiep)
393                                     ? (l_off_t)*cookiep
394                                     : (l_off_t)(off + reclen);
395                                 linux_dirent.d_reclen = (l_ushort)linuxreclen;
396                                 strcpy(linux_dirent.d_name, bdp->d_name);
397                                 error = copyout(&linux_dirent, outp,
398                                     linuxreclen);
399                         }
400                 }
401                 if (error)
402                         goto out;
403
404                 inp += reclen;
405                 if (cookiep) {
406                         off = *cookiep++;
407                         ncookies--;
408                 } else
409                         off += reclen;
410
411                 outp += linuxreclen;
412                 resid -= linuxreclen;
413                 len -= reclen;
414                 if (justone)
415                         break;
416         }
417
418         if (outp == (caddr_t)args->dirent)
419                 goto again;
420
421         fp->f_offset = off;
422         if (justone)
423                 nbytes = resid + linuxreclen;
424
425 eof:
426         p->p_retval[0] = nbytes - resid;
427
428 out:
429         if (cookies)
430                 free(cookies, M_TEMP);
431
432         VOP_UNLOCK(vp, 0, p);
433         free(buf, M_TEMP);
434         return (error);
435 }
436
437 int
438 linux_getdents(struct proc *p, struct linux_getdents_args *args)
439 {
440
441 #ifdef DEBUG
442         if (ldebug(getdents))
443                 printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count);
444 #endif
445
446         return (getdents_common(p, (struct linux_getdents64_args*)args, 0));
447 }
448
449 int
450 linux_getdents64(struct proc *p, struct linux_getdents64_args *args)
451 {
452
453 #ifdef DEBUG
454         if (ldebug(getdents64))
455                 printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count);
456 #endif
457
458         return (getdents_common(p, args, 1));
459 }
460
461 /*
462  * These exist mainly for hooks for doing /compat/linux translation.
463  */
464
465 int
466 linux_access(struct proc *p, struct linux_access_args *args)
467 {
468         struct access_args bsd;
469         caddr_t sg;
470
471         sg = stackgap_init();
472         CHECKALTEXIST(p, &sg, args->path);
473
474 #ifdef DEBUG
475         if (ldebug(access))
476                 printf(ARGS(access, "%s, %d"), args->path, args->flags);
477 #endif
478         bsd.path = args->path;
479         bsd.flags = args->flags;
480
481         return access(p, &bsd);
482 }
483
484 int
485 linux_unlink(struct proc *p, struct linux_unlink_args *args)
486 {
487         struct unlink_args bsd;
488         caddr_t sg;
489
490         sg = stackgap_init();
491         CHECKALTEXIST(p, &sg, args->path);
492
493 #ifdef DEBUG
494         if (ldebug(unlink))
495                 printf(ARGS(unlink, "%s"), args->path);
496 #endif
497         bsd.path = args->path;
498
499         return unlink(p, &bsd);
500 }
501
502 int
503 linux_chdir(struct proc *p, struct linux_chdir_args *args)
504 {
505         struct chdir_args bsd;
506         caddr_t sg;
507
508         sg = stackgap_init();
509         CHECKALTEXIST(p, &sg, args->path);
510
511 #ifdef DEBUG
512         if (ldebug(chdir))
513                 printf(ARGS(chdir, "%s"), args->path);
514 #endif
515         bsd.path = args->path;
516
517         return chdir(p, &bsd);
518 }
519
520 int
521 linux_chmod(struct proc *p, struct linux_chmod_args *args)
522 {
523         struct chmod_args bsd;
524         caddr_t sg;
525
526         sg = stackgap_init();
527         CHECKALTEXIST(p, &sg, args->path);
528
529 #ifdef DEBUG
530         if (ldebug(chmod))
531                 printf(ARGS(chmod, "%s, %d"), args->path, args->mode);
532 #endif
533         bsd.path = args->path;
534         bsd.mode = args->mode;
535
536         return chmod(p, &bsd);
537 }
538
539 int
540 linux_mkdir(struct proc *p, struct linux_mkdir_args *args)
541 {
542         struct mkdir_args bsd;
543         caddr_t sg;
544
545         sg = stackgap_init();
546         CHECKALTCREAT(p, &sg, args->path);
547
548 #ifdef DEBUG
549         if (ldebug(mkdir))
550                 printf(ARGS(mkdir, "%s, %d"), args->path, args->mode);
551 #endif
552         bsd.path = args->path;
553         bsd.mode = args->mode;
554
555         return mkdir(p, &bsd);
556 }
557
558 int
559 linux_rmdir(struct proc *p, struct linux_rmdir_args *args)
560 {
561         struct rmdir_args bsd;
562         caddr_t sg;
563
564         sg = stackgap_init();
565         CHECKALTEXIST(p, &sg, args->path);
566
567 #ifdef DEBUG
568         if (ldebug(rmdir))
569                 printf(ARGS(rmdir, "%s"), args->path);
570 #endif
571         bsd.path = args->path;
572
573         return rmdir(p, &bsd);
574 }
575
576 int
577 linux_rename(struct proc *p, struct linux_rename_args *args)
578 {
579         struct rename_args bsd;
580         caddr_t sg;
581
582         sg = stackgap_init();
583         CHECKALTEXIST(p, &sg, args->from);
584         CHECKALTCREAT(p, &sg, args->to);
585
586 #ifdef DEBUG
587         if (ldebug(rename))
588                 printf(ARGS(rename, "%s, %s"), args->from, args->to);
589 #endif
590         bsd.from = args->from;
591         bsd.to = args->to;
592
593         return rename(p, &bsd);
594 }
595
596 int
597 linux_symlink(struct proc *p, struct linux_symlink_args *args)
598 {
599         struct symlink_args bsd;
600         caddr_t sg;
601
602         sg = stackgap_init();
603         CHECKALTEXIST(p, &sg, args->path);
604         CHECKALTCREAT(p, &sg, args->to);
605
606 #ifdef DEBUG
607         if (ldebug(symlink))
608                 printf(ARGS(symlink, "%s, %s"), args->path, args->to);
609 #endif
610         bsd.path = args->path;
611         bsd.link = args->to;
612
613         return symlink(p, &bsd);
614 }
615
616 int
617 linux_readlink(struct proc *p, struct linux_readlink_args *args)
618 {
619         struct readlink_args bsd;
620         caddr_t sg;
621
622         sg = stackgap_init();
623         CHECKALTEXIST(p, &sg, args->name);
624
625 #ifdef DEBUG
626         if (ldebug(readlink))
627                 printf(ARGS(readlink, "%s, %p, %d"),
628                     args->name, (void *)args->buf, args->count);
629 #endif
630         bsd.path = args->name;
631         bsd.buf = args->buf;
632         bsd.count = args->count;
633
634         return readlink(p, &bsd);
635 }
636
637 int
638 linux_truncate(struct proc *p, struct linux_truncate_args *args)
639 {
640         struct truncate_args bsd;
641         caddr_t sg;
642
643         sg = stackgap_init();
644         CHECKALTEXIST(p, &sg, args->path);
645
646 #ifdef DEBUG
647         if (ldebug(truncate))
648                 printf(ARGS(truncate, "%s, %ld"), args->path,
649                     (long)args->length);
650 #endif
651         bsd.path = args->path;
652         bsd.length = args->length;
653
654         return truncate(p, &bsd);
655 }
656
657 int
658 linux_link(struct proc *p, struct linux_link_args *args)
659 {
660     struct link_args bsd;
661     caddr_t sg;
662
663     sg = stackgap_init();
664     CHECKALTEXIST(p, &sg, args->path);
665     CHECKALTCREAT(p, &sg, args->to);
666
667 #ifdef DEBUG
668         if (ldebug(link))
669                 printf(ARGS(link, "%s, %s"), args->path, args->to);
670 #endif
671
672     bsd.path = args->path;
673     bsd.link = args->to;
674
675     return link(p, &bsd);
676 }
677
678 #ifndef __alpha__
679 int
680 linux_fdatasync(p, uap)
681         struct proc *p;
682         struct linux_fdatasync_args *uap;
683 {
684         struct fsync_args bsd;
685
686         bsd.fd = uap->fd;
687         return fsync(p, &bsd);
688 }
689 #endif /*!__alpha__*/
690
691 int
692 linux_pread(p, uap)
693         struct proc *p;
694         struct linux_pread_args *uap;
695 {
696         struct pread_args bsd;
697
698         bsd.fd = uap->fd;
699         bsd.buf = uap->buf;
700         bsd.nbyte = uap->nbyte;
701         bsd.offset = uap->offset;
702         return pread(p, &bsd);
703 }
704
705 int
706 linux_pwrite(p, uap)
707         struct proc *p;
708         struct linux_pwrite_args *uap;
709 {
710         struct pwrite_args bsd;
711
712         bsd.fd = uap->fd;
713         bsd.buf = uap->buf;
714         bsd.nbyte = uap->nbyte;
715         bsd.offset = uap->offset;
716         return pwrite(p, &bsd);
717 }
718
719 int
720 linux_oldumount(struct proc *p, struct linux_oldumount_args *args)
721 {
722         struct linux_umount_args args2;
723
724         args2.path = args->path;
725         args2.flags = 0;
726         return (linux_umount(p, &args2));
727 }
728
729 int
730 linux_umount(struct proc *p, struct linux_umount_args *args)
731 {
732         struct unmount_args bsd;
733
734         bsd.path = args->path;
735         bsd.flags = args->flags;        /* XXX correct? */
736         return (unmount(p, &bsd));
737 }
738
739 /*
740  * fcntl family of syscalls
741  */
742
743 struct l_flock {
744         l_short         l_type;
745         l_short         l_whence;
746         l_off_t         l_start;
747         l_off_t         l_len;
748         l_pid_t         l_pid;
749 };
750
751 static void
752 linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
753 {
754         switch (linux_flock->l_type) {
755         case LINUX_F_RDLCK:
756                 bsd_flock->l_type = F_RDLCK;
757                 break;
758         case LINUX_F_WRLCK:
759                 bsd_flock->l_type = F_WRLCK;
760                 break;
761         case LINUX_F_UNLCK:
762                 bsd_flock->l_type = F_UNLCK;
763                 break;
764         default:
765                 bsd_flock->l_type = -1;
766                 break;
767         }
768         bsd_flock->l_whence = linux_flock->l_whence;
769         bsd_flock->l_start = (off_t)linux_flock->l_start;
770         bsd_flock->l_len = (off_t)linux_flock->l_len;
771         bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
772 }
773
774 static void
775 bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
776 {
777         switch (bsd_flock->l_type) {
778         case F_RDLCK:
779                 linux_flock->l_type = LINUX_F_RDLCK;
780                 break;
781         case F_WRLCK:
782                 linux_flock->l_type = LINUX_F_WRLCK;
783                 break;
784         case F_UNLCK:
785                 linux_flock->l_type = LINUX_F_UNLCK;
786                 break;
787         }
788         linux_flock->l_whence = bsd_flock->l_whence;
789         linux_flock->l_start = (l_off_t)bsd_flock->l_start;
790         linux_flock->l_len = (l_off_t)bsd_flock->l_len;
791         linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
792 }
793
794 #if defined(__i386__)
795 struct l_flock64 {
796         l_short         l_type;
797         l_short         l_whence;
798         l_loff_t        l_start;
799         l_loff_t        l_len;
800         l_pid_t         l_pid;
801 };
802
803 static void
804 linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
805 {
806         switch (linux_flock->l_type) {
807         case LINUX_F_RDLCK:
808                 bsd_flock->l_type = F_RDLCK;
809                 break;
810         case LINUX_F_WRLCK:
811                 bsd_flock->l_type = F_WRLCK;
812                 break;
813         case LINUX_F_UNLCK:
814                 bsd_flock->l_type = F_UNLCK;
815                 break;
816         default:
817                 bsd_flock->l_type = -1;
818                 break;
819         }
820         bsd_flock->l_whence = linux_flock->l_whence;
821         bsd_flock->l_start = (off_t)linux_flock->l_start;
822         bsd_flock->l_len = (off_t)linux_flock->l_len;
823         bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
824 }
825
826 static void
827 bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
828 {
829         switch (bsd_flock->l_type) {
830         case F_RDLCK:
831                 linux_flock->l_type = LINUX_F_RDLCK;
832                 break;
833         case F_WRLCK:
834                 linux_flock->l_type = LINUX_F_WRLCK;
835                 break;
836         case F_UNLCK:
837                 linux_flock->l_type = LINUX_F_UNLCK;
838                 break;
839         }
840         linux_flock->l_whence = bsd_flock->l_whence;
841         linux_flock->l_start = (l_loff_t)bsd_flock->l_start;
842         linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
843         linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
844 }
845 #endif /* __i386__ */
846
847 #if defined(__alpha__)
848 #define linux_fcntl64_args      linux_fcntl_args
849 #endif
850
851 static int
852 fcntl_common(struct proc *p, struct linux_fcntl64_args *args)
853 {
854         struct l_flock linux_flock;
855         struct flock *bsd_flock;
856         struct fcntl_args fcntl_args;
857         struct filedesc *fdp;
858         struct file *fp;
859         int error, result;
860         caddr_t sg;
861
862         sg = stackgap_init();
863         bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock));
864
865         fcntl_args.fd = args->fd;
866
867         switch (args->cmd) {
868         case LINUX_F_DUPFD:
869                 fcntl_args.cmd = F_DUPFD;
870                 fcntl_args.arg = args->arg;
871                 return (fcntl(p, &fcntl_args));
872
873         case LINUX_F_GETFD:
874                 fcntl_args.cmd = F_GETFD;
875                 return (fcntl(p, &fcntl_args));
876
877         case LINUX_F_SETFD:
878                 fcntl_args.cmd = F_SETFD;
879                 fcntl_args.arg = args->arg;
880                 return (fcntl(p, &fcntl_args));
881
882         case LINUX_F_GETFL:
883                 fcntl_args.cmd = F_GETFL;
884                 error = fcntl(p, &fcntl_args);
885                 result = p->p_retval[0];
886                 p->p_retval[0] = 0;
887                 if (result & O_RDONLY)
888                         p->p_retval[0] |= LINUX_O_RDONLY;
889                 if (result & O_WRONLY)
890                         p->p_retval[0] |= LINUX_O_WRONLY;
891                 if (result & O_RDWR)
892                         p->p_retval[0] |= LINUX_O_RDWR;
893                 if (result & O_NDELAY)
894                         p->p_retval[0] |= LINUX_O_NONBLOCK;
895                 if (result & O_APPEND)
896                         p->p_retval[0] |= LINUX_O_APPEND;
897                 if (result & O_FSYNC)
898                         p->p_retval[0] |= LINUX_O_SYNC;
899                 if (result & O_ASYNC)
900                         p->p_retval[0] |= LINUX_FASYNC;
901                 return (error);
902
903         case LINUX_F_SETFL:
904                 fcntl_args.arg = 0;
905                 if (args->arg & LINUX_O_NDELAY)
906                         fcntl_args.arg |= O_NONBLOCK;
907                 if (args->arg & LINUX_O_APPEND)
908                         fcntl_args.arg |= O_APPEND;
909                 if (args->arg & LINUX_O_SYNC)
910                         fcntl_args.arg |= O_FSYNC;
911                 if (args->arg & LINUX_FASYNC)
912                         fcntl_args.arg |= O_ASYNC;
913                 fcntl_args.cmd = F_SETFL;
914                 return (fcntl(p, &fcntl_args));
915
916         case LINUX_F_GETLK:
917                 error = copyin((caddr_t)args->arg, &linux_flock,
918                     sizeof(linux_flock));
919                 if (error)
920                         return (error);
921                 linux_to_bsd_flock(&linux_flock, bsd_flock);
922                 fcntl_args.fd = args->fd;
923                 fcntl_args.cmd = F_GETLK;
924                 fcntl_args.arg = (long)bsd_flock;
925                 error = fcntl(p, &fcntl_args);
926                 if (error)
927                         return (error);
928                 bsd_to_linux_flock(bsd_flock, &linux_flock);
929                 return (copyout(&linux_flock, (caddr_t)args->arg,
930                     sizeof(linux_flock)));
931
932         case LINUX_F_SETLK:
933                 error = copyin((caddr_t)args->arg, &linux_flock,
934                     sizeof(linux_flock));
935                 if (error)
936                         return (error);
937                 linux_to_bsd_flock(&linux_flock, bsd_flock);
938                 fcntl_args.fd = args->fd;
939                 fcntl_args.cmd = F_SETLK;
940                 fcntl_args.arg = (long)bsd_flock;
941                 return (fcntl(p, &fcntl_args));
942
943         case LINUX_F_SETLKW:
944                 error = copyin((caddr_t)args->arg, &linux_flock,
945                     sizeof(linux_flock));
946                 if (error)
947                         return (error);
948                 linux_to_bsd_flock(&linux_flock, bsd_flock);
949                 fcntl_args.fd = args->fd;
950                 fcntl_args.cmd = F_SETLKW;
951                 fcntl_args.arg = (long)bsd_flock;
952                 return (fcntl(p, &fcntl_args));
953
954         case LINUX_F_GETOWN:
955                 fcntl_args.cmd = F_GETOWN;
956                 return (fcntl(p, &fcntl_args));
957
958         case LINUX_F_SETOWN:
959                 /*
960                  * XXX some Linux applications depend on F_SETOWN having no
961                  * significant effect for pipes (SIGIO is not delivered for
962                  * pipes under Linux-2.2.35 at least).
963                  */
964                 fdp = p->p_fd;
965                 if ((u_int)args->fd >= fdp->fd_nfiles ||
966                     (fp = fdp->fd_ofiles[args->fd]) == NULL)
967                         return (EBADF);
968                 if (fp->f_type == DTYPE_PIPE)
969                         return (EINVAL);
970
971                 fcntl_args.cmd = F_SETOWN;
972                 fcntl_args.arg = args->arg;
973                 return (fcntl(p, &fcntl_args));
974         }
975
976         return (EINVAL);
977 }
978
979 int
980 linux_fcntl(struct proc *p, struct linux_fcntl_args *args)
981 {
982         struct linux_fcntl64_args args64;
983
984 #ifdef DEBUG
985         if (ldebug(fcntl))
986                 printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
987 #endif
988
989         args64.fd = args->fd;
990         args64.cmd = args->cmd;
991         args64.arg = args->arg;
992         return (fcntl_common(p, &args64));
993 }
994
995 #if defined(__i386__)
996 int
997 linux_fcntl64(struct proc *p, struct linux_fcntl64_args *args)
998 {
999         struct fcntl_args fcntl_args;
1000         struct l_flock64 linux_flock;
1001         struct flock *bsd_flock;
1002         int error;
1003         caddr_t sg;
1004
1005         sg = stackgap_init();
1006         bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock));
1007
1008 #ifdef DEBUG
1009         if (ldebug(fcntl64))
1010                 printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd);
1011 #endif
1012
1013         switch (args->cmd) {
1014         case LINUX_F_GETLK64:
1015                 error = copyin((caddr_t)args->arg, &linux_flock,
1016                     sizeof(linux_flock));
1017                 if (error)
1018                         return (error);
1019                 linux_to_bsd_flock64(&linux_flock, bsd_flock);
1020                 fcntl_args.fd = args->fd;
1021                 fcntl_args.cmd = F_GETLK;
1022                 fcntl_args.arg = (long)bsd_flock;
1023                 error = fcntl(p, &fcntl_args);
1024                 if (error)
1025                         return (error);
1026                 bsd_to_linux_flock64(bsd_flock, &linux_flock);
1027                 return (copyout(&linux_flock, (caddr_t)args->arg,
1028                     sizeof(linux_flock)));
1029
1030         case LINUX_F_SETLK64:
1031                 error = copyin((caddr_t)args->arg, &linux_flock,
1032                     sizeof(linux_flock));
1033                 if (error)
1034                         return (error);
1035                 linux_to_bsd_flock64(&linux_flock, bsd_flock);
1036                 fcntl_args.fd = args->fd;
1037                 fcntl_args.cmd = F_SETLK;
1038                 fcntl_args.arg = (long)bsd_flock;
1039                 return (fcntl(p, &fcntl_args));
1040
1041         case LINUX_F_SETLKW64:
1042                 error = copyin((caddr_t)args->arg, &linux_flock,
1043                     sizeof(linux_flock));
1044                 if (error)
1045                         return (error);
1046                 linux_to_bsd_flock64(&linux_flock, bsd_flock);
1047                 fcntl_args.fd = args->fd;
1048                 fcntl_args.cmd = F_SETLKW;
1049                 fcntl_args.arg = (long)bsd_flock;
1050                 return (fcntl(p, &fcntl_args));
1051         }
1052
1053         return (fcntl_common(p, args));
1054 }
1055 #endif /* __i386__ */
1056
1057 int
1058 linux_chown(struct proc *p, struct linux_chown_args *args)
1059 {
1060         struct chown_args bsd;
1061         caddr_t sg;
1062
1063         sg = stackgap_init();
1064         CHECKALTEXIST(p, &sg, args->path);
1065
1066 #ifdef DEBUG
1067         if (ldebug(chown))
1068                 printf(ARGS(chown, "%s, %d, %d"), args->path, args->uid,
1069                     args->gid);
1070 #endif
1071
1072         bsd.path = args->path;
1073         bsd.uid = args->uid;
1074         bsd.gid = args->gid;
1075         return (chown(p, &bsd));
1076 }
1077
1078 int
1079 linux_lchown(struct proc *p, struct linux_lchown_args *args)
1080 {
1081         struct lchown_args bsd;
1082         caddr_t sg;
1083
1084         sg = stackgap_init();
1085         CHECKALTEXIST(p, &sg, args->path);
1086
1087 #ifdef DEBUG
1088         if (ldebug(lchown))
1089                 printf(ARGS(lchown, "%s, %d, %d"), args->path, args->uid,
1090                     args->gid);
1091 #endif
1092
1093         bsd.path = args->path;
1094         bsd.uid = args->uid;
1095         bsd.gid = args->gid;
1096         return (lchown(p, &bsd));
1097 }