The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/emulation/linux/linux_file.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: a32cb68440e826b7fa42635eb16ee0e9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.