[BACK]Return to compat_dir.c CVS log [TXT][DIR] Up to [local] / sys / compat / common

Annotation of sys/compat/common/compat_dir.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: compat_dir.c,v 1.4 2003/08/14 16:55:24 fgsch Exp $    */
                      2:
                      3: /*
                      4:  * Copyright (c) 2000 Constantine Sapuntzakis
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. The name of the author may not be used to endorse or promote products
                     13:  *    derived from this software without specific prior written permission
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     17:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     18:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     19:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     20:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     21:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     22:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     23:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     24:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     25:  *
                     26:  */
                     27:
                     28: #include <sys/param.h>
                     29: #include <sys/systm.h>
                     30: #include <sys/namei.h>
                     31: #include <sys/proc.h>
                     32: #include <sys/file.h>
                     33: #include <sys/stat.h>
                     34: #include <sys/filedesc.h>
                     35: #include <sys/ioctl.h>
                     36: #include <sys/kernel.h>
                     37: #include <sys/malloc.h>
                     38: #include <sys/vnode.h>
                     39: #include <sys/dirent.h>
                     40:
                     41: #include <compat/common/compat_dir.h>
                     42:
                     43: int
                     44: readdir_with_callback(fp, off, nbytes, appendfunc, arg)
                     45:        struct file *fp;
                     46:        off_t *off;
                     47:        u_long nbytes;
                     48:        int (*appendfunc)(void *, struct dirent *, off_t);
                     49:        void *arg;
                     50: {
                     51:        struct dirent *bdp;
                     52:        caddr_t inp, buf;
                     53:        int buflen;
                     54:        struct uio auio;
                     55:        struct iovec aiov;
                     56:        int eofflag = 0;
                     57:        u_long *cookies = NULL, *cookiep;
                     58:        int ncookies = 0;
                     59:        int error, len, reclen;
                     60:        off_t newoff = *off;
                     61:        struct vnode *vp;
                     62:        struct vattr va;
                     63:
                     64:        if ((fp->f_flag & FREAD) == 0)
                     65:                return (EBADF);
                     66:
                     67:        vp = (struct vnode *)fp->f_data;
                     68:
                     69:        if (vp->v_type != VDIR)
                     70:                return (EINVAL);
                     71:
                     72:        if ((error = VOP_GETATTR(vp, &va, fp->f_cred, curproc)) != 0)
                     73:                return (error);
                     74:
                     75:        buflen = min(MAXBSIZE, nbytes);
                     76:        buflen = max(buflen, va.va_blocksize);
                     77:        buf = malloc(buflen, M_TEMP, M_WAITOK);
                     78:        error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
                     79:        if (error)
                     80:                goto out;
                     81:
                     82: again:
                     83:        aiov.iov_base = buf;
                     84:        aiov.iov_len = buflen;
                     85:        auio.uio_iov = &aiov;
                     86:        auio.uio_iovcnt = 1;
                     87:        auio.uio_rw = UIO_READ;
                     88:        auio.uio_segflg = UIO_SYSSPACE;
                     89:        auio.uio_procp = curproc;
                     90:        auio.uio_resid = buflen;
                     91:        auio.uio_offset = newoff;
                     92:
                     93:        if (cookies) {
                     94:                free(cookies, M_TEMP);
                     95:                cookies = NULL;
                     96:        }
                     97:
                     98:        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
                     99:            &cookies);
                    100:        if (error)
                    101:                goto out;
                    102:
                    103:        if ((len = buflen - auio.uio_resid) <= 0)
                    104:                goto eof;
                    105:
                    106:        cookiep = cookies;
                    107:        inp = buf;
                    108:
                    109:        if (cookies) {
                    110:                /*
                    111:                 * When using cookies, the vfs has the option of reading from
                    112:                 * a different offset than that supplied (UFS truncates the
                    113:                 * offset to a block boundary to make sure that it never reads
                    114:                 * partway through a directory entry, even if the directory
                    115:                 * has been compacted).
                    116:                 */
                    117:                while (len > 0 && ncookies > 0 && *cookiep <= newoff) {
                    118:                        bdp = (struct dirent *)inp;
                    119:                        len -= bdp->d_reclen;
                    120:                        inp += bdp->d_reclen;
                    121:                        cookiep++;
                    122:                        ncookies--;
                    123:                }
                    124:        }
                    125:
                    126:        for (; len > 0; len -= reclen, inp += reclen) {
                    127:                if (cookiep && ncookies == 0)
                    128:                        break;
                    129:
                    130:                bdp = (struct dirent *)inp;
                    131:                reclen = bdp->d_reclen;
                    132:
                    133:                if (len < reclen)
                    134:                        break;
                    135:
                    136:                if (reclen & 3) {
                    137:                        error = EFAULT;
                    138:                        goto out;
                    139:                }
                    140:
                    141:                /* Skip holes */
                    142:                if (bdp->d_fileno != 0) {
                    143:                        if ((error = (*appendfunc) (arg, bdp,
                    144:                            (cookiep) ? *cookiep : (newoff + reclen))) != 0) {
                    145:                                if (error == ENOMEM)
                    146:                                        error = 0;
                    147:                                break;
                    148:                        }
                    149:                }
                    150:
                    151:                if (cookiep) {
                    152:                        newoff = *cookiep++;
                    153:                        ncookies--;
                    154:                } else
                    155:                        newoff += reclen;
                    156:        }
                    157:
                    158:        if (len <= 0 && !eofflag)
                    159:                goto again;
                    160:
                    161: eof:
                    162: out:
                    163:        if (error == 0)
                    164:                *off = newoff;
                    165:
                    166:        if (cookies)
                    167:                free(cookies, M_TEMP);
                    168:
                    169:        VOP_UNLOCK(vp, 0, curproc);
                    170:        free(buf, M_TEMP);
                    171:        return (error);
                    172: }

CVSweb