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

Cache object: 5092b0167815ef6ae7f27b6c01e36484


[ 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.