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/irix/irix_dirent.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 /*      $NetBSD: irix_dirent.c,v 1.23.10.1 2010/03/17 02:59:52 snj Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1994, 2001, 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Christos Zoulas and Emmanuel Dreyfus.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: irix_dirent.c,v 1.23.10.1 2010/03/17 02:59:52 snj Exp $");
   34 
   35 #include <sys/types.h>
   36 #include <sys/signal.h>
   37 #include <sys/param.h>
   38 #include <sys/proc.h>
   39 #include <sys/dirent.h>
   40 #include <sys/fcntl.h>
   41 #include <sys/file.h>
   42 #include <sys/filedesc.h>
   43 #include <sys/mount.h>
   44 #include <sys/malloc.h>
   45 #include <sys/namei.h>
   46 #include <sys/systm.h>
   47 #include <sys/vnode.h>
   48 
   49 #include <compat/common/compat_util.h>
   50 
   51 #include <compat/irix/irix_types.h>
   52 #include <compat/irix/irix_signal.h>
   53 #include <compat/irix/irix_syscall.h>
   54 #include <compat/irix/irix_syscallargs.h>
   55 
   56 /*
   57  * irix_sys_ngetdents() is nearly a plain copy of svr4_sys_getdents(), from
   58  * sys/compat/svr4/svr4_misc.c. We need a customized version to handle the
   59  * eof flag.
   60  * Obviously the code should be merged, but it would require some
   61  * change to the way COMPAT_SVR4 code is set up.
   62  */
   63 #define SVR4_RECLEN(de,namlen) ALIGN((SVR4_NAMEOFF(de) + (namlen) + 1))
   64 #define SVR4_NAMEOFF(dp)       ((char *)&(dp)->d_name - (char *)dp)
   65 
   66 int
   67 irix_sys_ngetdents(struct lwp *l, const struct irix_sys_ngetdents_args *uap, register_t *retval)
   68 {
   69         /* {
   70                 syscallarg(int) fildes;
   71                 syscallarg(irix_dirent_t *) buf;
   72                 syscallarg(unsigned short) nbyte;
   73                 syscallarg(int *) eof;
   74         } */
   75         struct dirent *bdp;
   76         struct vnode *vp;
   77         char *inp, *buf;        /* BSD-format */
   78         int len, reclen;        /* BSD-format */
   79         char *outp;             /* SVR4-format */
   80         int resid, svr4_reclen; /* SVR4-format */
   81         struct file *fp;
   82         struct uio auio;
   83         struct iovec aiov;
   84         struct irix_dirent idb;
   85         off_t off;              /* true file offset */
   86         int buflen, error, eofflag;
   87         off_t *cookiebuf = NULL, *cookie;
   88         int ncookies, fd;
   89 
   90         fd = SCARG(uap, fildes);
   91         if ((error = fd_getvnode(fd, &fp)) != 0)
   92                 return (error);
   93 
   94         if ((fp->f_flag & FREAD) == 0) {
   95                 error = EBADF;
   96                 goto out1;
   97         }
   98 
   99         vp = (struct vnode *)fp->f_data;
  100         if (vp->v_type != VDIR) {
  101                 error = EINVAL;
  102                 goto out1;
  103         }
  104 
  105         buflen = min(MAXBSIZE, SCARG(uap, nbyte));
  106         buf = malloc(buflen, M_TEMP, M_WAITOK);
  107         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  108         off = fp->f_offset;
  109 again:
  110         aiov.iov_base = buf;
  111         aiov.iov_len = buflen;
  112         auio.uio_iov = &aiov;
  113         auio.uio_iovcnt = 1;
  114         auio.uio_rw = UIO_READ;
  115         auio.uio_resid = buflen;
  116         auio.uio_offset = off;
  117         UIO_SETUP_SYSSPACE(&auio);
  118         /*
  119          * First we read into the malloc'ed buffer, then
  120          * we massage it into user space, one record at a time.
  121          */
  122         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
  123             &ncookies);
  124         if (error)
  125                 goto out;
  126 
  127         inp = buf;
  128         outp = (char *)SCARG(uap, buf);
  129         resid = SCARG(uap, nbyte);
  130         if ((len = buflen - auio.uio_resid) == 0)
  131                 goto eof;
  132 
  133         for (cookie = cookiebuf; len > 0; len -= reclen) {
  134                 bdp = (struct dirent *)inp;
  135                 reclen = bdp->d_reclen;
  136                 if (reclen & 3)
  137                         panic("irix_getdents: bad reclen");
  138                 if (cookie)
  139                         off = *cookie++; /* each entry points to the next */
  140                 else
  141                         off += reclen;
  142                 if ((off >> 32) != 0) {
  143                         compat_offseterr(vp, "irix_getdents");
  144                         error = EINVAL;
  145                         goto out;
  146                 }
  147                 if (bdp->d_fileno == 0) {
  148                         inp += reclen;  /* it is a hole; squish it out */
  149                         continue;
  150                 }
  151                 svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
  152                 if (reclen > len || resid < svr4_reclen) {
  153                         /* entry too big for buffer, so just stop */
  154                         outp++;
  155                         break;
  156                 }
  157                 /*
  158                  * Massage in place to make a SVR4-shaped dirent (otherwise
  159                  * we have to worry about touching user memory outside of
  160                  * the copyout() call).
  161                  */
  162                 idb.d_ino = (irix_ino_t)bdp->d_fileno;
  163                 idb.d_off = (irix_off_t)off;
  164                 idb.d_reclen = (u_short)svr4_reclen;
  165                 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
  166                 if ((error = copyout((void *)&idb, outp, svr4_reclen)))
  167                         goto out;
  168                 /* advance past this real entry */
  169                 inp += reclen;
  170                 /* advance output past SVR4-shaped entry */
  171                 outp += svr4_reclen;
  172                 resid -= svr4_reclen;
  173         }
  174 
  175         /* if we squished out the whole block, try again */
  176         if (outp == (char *)SCARG(uap, buf)) {
  177                 if (cookiebuf)
  178                         free(cookiebuf, M_TEMP);
  179                 cookiebuf = NULL;
  180                 goto again;
  181         }
  182         fp->f_offset = off;     /* update the vnode offset */
  183 
  184 eof:
  185         *retval = SCARG(uap, nbyte) - resid;
  186 out:
  187         VOP_UNLOCK(vp, 0);
  188         if (cookiebuf)
  189                 free(cookiebuf, M_TEMP);
  190         free(buf, M_TEMP);
  191 out1:
  192         fd_putfile(fd);
  193         if (SCARG(uap, eof) != NULL)
  194                 error = copyout(&eofflag, SCARG(uap, eof), sizeof(int));
  195         return error;
  196 }
  197 
  198 int
  199 irix_sys_getdents(struct lwp *l, const struct irix_sys_getdents_args *uap, register_t *retval)
  200 {
  201         /* {
  202                 syscallarg(int) fildes;
  203                 syscallarg(irix_dirent_t *) buf;
  204                 syscallarg(unsigned short) nbyte;
  205                 syscallarg(int *) eof;
  206         } */
  207         struct irix_sys_ngetdents_args cup;
  208 
  209         SCARG(&cup, fildes) = SCARG(uap, fildes);
  210         SCARG(&cup, buf) = SCARG(uap, buf);
  211         SCARG(&cup, nbyte) = SCARG(uap, nbytes);
  212         SCARG(&cup, eof) = NULL;
  213 
  214         return irix_sys_ngetdents(l, (void *)&cup, retval);
  215 }
  216 
  217 
  218 /*
  219  * The 64 versions are very close to the
  220  * 32 bit versions (only 3 lines of diff)
  221  */
  222 int
  223 irix_sys_ngetdents64(struct lwp *l, const struct irix_sys_ngetdents64_args *uap, register_t *retval)
  224 {
  225         /* {
  226                 syscallarg(int) fildes;
  227                 syscallarg(irix_dirent64_t *) buf;
  228                 syscallarg(unsigned short) nbyte;
  229                 syscallarg(int *) eof;
  230         } */
  231         struct dirent *bdp;
  232         struct vnode *vp;
  233         char *inp, *buf;        /* BSD-format */
  234         int len, reclen;        /* BSD-format */
  235         char *outp;             /* SVR4-format */
  236         int resid, svr4_reclen; /* SVR4-format */
  237         file_t *fp;
  238         struct uio auio;
  239         struct iovec aiov;
  240         struct irix_dirent64 idb;
  241         off_t off;              /* true file offset */
  242         int buflen, error, eofflag;
  243         off_t *cookiebuf = NULL, *cookie;
  244         int ncookies, fd;
  245 
  246         fd = SCARG(uap, fildes);
  247         if ((error = fd_getvnode(fd, &fp)) != 0)
  248                 return (error);
  249 
  250         if ((fp->f_flag & FREAD) == 0) {
  251                 error = EBADF;
  252                 goto out1;
  253         }
  254 
  255         vp = fp->f_data;
  256         if (vp->v_type != VDIR) {
  257                 error = EINVAL;
  258                 goto out1;
  259         }
  260 
  261         buflen = min(MAXBSIZE, SCARG(uap, nbyte));
  262         buf = malloc(buflen, M_TEMP, M_WAITOK);
  263         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  264         off = fp->f_offset;
  265 again:
  266         aiov.iov_base = buf;
  267         aiov.iov_len = buflen;
  268         auio.uio_iov = &aiov;
  269         auio.uio_iovcnt = 1;
  270         auio.uio_rw = UIO_READ;
  271         auio.uio_resid = buflen;
  272         auio.uio_offset = off;
  273         UIO_SETUP_SYSSPACE(&auio);
  274         /*
  275          * First we read into the malloc'ed buffer, then
  276          * we massage it into user space, one record at a time.
  277          */
  278         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
  279             &ncookies);
  280         if (error)
  281                 goto out;
  282 
  283         inp = buf;
  284         outp = (char *)SCARG(uap, buf);
  285         resid = SCARG(uap, nbyte);
  286         if ((len = buflen - auio.uio_resid) == 0)
  287                 goto eof;
  288 
  289         for (cookie = cookiebuf; len > 0; len -= reclen) {
  290                 bdp = (struct dirent *)inp;
  291                 reclen = bdp->d_reclen;
  292                 if (reclen & 3)
  293                         panic("irix_getdents64: bad reclen");
  294                 if (bdp->d_fileno == 0) {
  295                         inp += reclen;  /* it is a hole; squish it out */
  296                         if (cookie)
  297                                 off = *cookie++;
  298                         else
  299                                 off += reclen;
  300                         continue;
  301                 }
  302                 svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
  303                 if (reclen > len || resid < svr4_reclen) {
  304                         /* entry too big for buffer, so just stop */
  305                         outp++;
  306                         break;
  307                 }
  308                 if (cookie)
  309                         off = *cookie++; /* each entry points to the next */
  310                 else
  311                         off += reclen;
  312                 /*
  313                  * Massage in place to make a SVR4-shaped dirent (otherwise
  314                  * we have to worry about touching user memory outside of
  315                  * the copyout() call).
  316                  */
  317                 idb.d_ino = (irix_ino64_t)bdp->d_fileno;
  318                 idb.d_off = (irix_off64_t)off;
  319                 idb.d_reclen = (u_short)svr4_reclen;
  320                 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
  321                 if ((error = copyout((void *)&idb, outp, svr4_reclen)))
  322                         goto out;
  323                 /* advance past this real entry */
  324                 inp += reclen;
  325                 /* advance output past SVR4-shaped entry */
  326                 outp += svr4_reclen;
  327                 resid -= svr4_reclen;
  328         }
  329 
  330         /* if we squished out the whole block, try again */
  331         if (outp == (char *)SCARG(uap, buf)) {
  332                 if (cookiebuf)
  333                         free(cookiebuf, M_TEMP);
  334                 cookiebuf = NULL;
  335                 goto again;
  336         }
  337         fp->f_offset = off;     /* update the vnode offset */
  338 
  339 eof:
  340         *retval = SCARG(uap, nbyte) - resid;
  341 out:
  342         VOP_UNLOCK(vp, 0);
  343         if (cookiebuf)
  344                 free(cookiebuf, M_TEMP);
  345         free(buf, M_TEMP);
  346 out1:
  347         fd_putfile(fd);
  348         if (SCARG(uap, eof) != NULL)
  349                 error = copyout(&eofflag, SCARG(uap, eof), sizeof(int));
  350         return error;
  351 }
  352 
  353 int
  354 irix_sys_getdents64(struct lwp *l, const struct irix_sys_getdents64_args *uap, register_t *retval)
  355 {
  356         /* {
  357                 syscallarg(int) fildes;
  358                 syscallarg(irix_dirent64_t *) buf;
  359                 syscallarg(unsigned short) nbyte;
  360                 syscallarg(int *) eof;
  361         } */
  362         struct irix_sys_ngetdents64_args cup;
  363 
  364         SCARG(&cup, fildes) = SCARG(uap, fildes);
  365         SCARG(&cup, buf) = SCARG(uap, buf);
  366         SCARG(&cup, nbyte) = SCARG(uap, nbytes);
  367         SCARG(&cup, eof) = NULL;
  368 
  369         return irix_sys_ngetdents64(l, (void *)&cup, retval);
  370 }

Cache object: 936a65114cef0c704888b65c7022dea1


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