X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=libsysio%2Fsrc%2Fgetdirentries.c;h=151829d198e53606419ec1407eb2f2dc4fc3f042;hb=dfff88032a23483b085e1677afefd4e313aab1f0;hp=7e1a81f28beb7ae457d6d06c040b7b26c5c9788b;hpb=b8292c00324fbe9a25910ce53d03569186ea3e2c;p=fs%2Flustre-release.git diff --git a/libsysio/src/getdirentries.c b/libsysio/src/getdirentries.c index 7e1a81f..151829d 100644 --- a/libsysio/src/getdirentries.c +++ b/libsysio/src/getdirentries.c @@ -17,28 +17,6 @@ */ /* - * ############################################################################# - * # - * # This Cplant(TM) source code is the property of Sandia National - * # Laboratories. - * # - * # This Cplant(TM) source code is copyrighted by Sandia National - * # Laboratories. - * # - * # The redistribution of this Cplant(TM) source code is subject to the - * # terms of the GNU Lesser General Public License - * # (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html) - * # - * # Cplant(TM) Copyright 1998-2004 Sandia Corporation. - * # Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive - * # license for use of this work by or on behalf of the US Government. - * # Export of this program may require a license from the United States - * # Government. - * # - * ############################################################################# - */ - -/* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -85,6 +63,28 @@ #endif static ssize_t +filldirents(struct file *fil, + char *buf, size_t nbytes, + _SYSIO_OFF_T *__restrict basep) +{ + _SYSIO_OFF_T opos; + ssize_t cc; + + if (!S_ISDIR(fil->f_ino->i_stbuf.st_mode)) + return -ENOTDIR; + + opos = fil->f_pos; + cc = + (*fil->f_ino->i_ops.inop_filldirentries)(fil->f_ino, + &fil->f_pos, + buf, nbytes); + if (cc < 0) + return cc; + *basep = opos; + return cc; +} + +static ssize_t PREPEND(_, SYSIO_INTERFACE_NAME(getdirentries64))(int fd, char *buf, size_t nbytes, @@ -98,21 +98,15 @@ PREPEND(_, SYSIO_INTERFACE_NAME(getdirentries64))(int fd, SYSIO_INTERFACE_ENTER; fil = _sysio_fd_find(fd); - if (!(fil && fil->f_ino)) + if (!(fil && fil->f_ino)) { SYSIO_INTERFACE_RETURN(-1, -EBADF); + } - if (!S_ISDIR(fil->f_ino->i_mode)) - SYSIO_INTERFACE_RETURN(-1, -ENOTDIR); - - cc = - (*fil->f_ino->i_ops.inop_getdirentries)(fil->f_ino, - buf, - nbytes, - basep); + cc = filldirents(fil, buf, nbytes, basep); SYSIO_INTERFACE_RETURN(cc < 0 ? -1 : cc, cc < 0 ? (int )cc : 0); } -#if _LARGEFILE64_SOURCE +#ifdef _LARGEFILE64_SOURCE #undef getdirentries64 sysio_sym_strong_alias(PREPEND(_, SYSIO_INTERFACE_NAME(getdirentries64)), SYSIO_INTERFACE_NAME(getdirentries64)) @@ -137,6 +131,17 @@ sysio_sym_strong_alias(PREPEND(_, SYSIO_INTERFACE_NAME(getdirentries64)), ((((n) + (boundary) - 1 ) / (boundary)) * (boundary)) #endif +#define _dbaselen ((size_t )&((struct dirent *)0)->d_name[0]) + +#ifdef __GLIBC__ +#define _dreclen(namlen) \ + ((_dbaselen + (namlen) + __alignof__ (struct dirent)) & \ + ~(__alignof__ (struct dirent) - 1)) +#else /* !defined(__GLIBC__) */ +#define _dreclen(namlen) \ + _rndup(_dbaselen + (namlen) + 1, sizeof(int)) +#endif + #ifndef BSD ssize_t SYSIO_INTERFACE_NAME(getdirentries)(int fd, @@ -151,144 +156,84 @@ SYSIO_INTERFACE_NAME(getdirentries)(int fd, long * __restrict basep) #endif { - size_t inbytes; - void *ibuf; - _SYSIO_OFF_T ibase; - ssize_t cc; - struct dirent *dp, *nxtdp; -#if defined(BSD) - int off; -#endif - struct intnl_dirent *od64p, *d64p; - size_t n; - size_t reclen; + struct file *fil; + _SYSIO_OFF_T b; + ssize_t cc, count; + struct dirent64 *d64p, d64; + struct dirent *dp; + size_t n, reclen; + void *p; char *cp; SYSIO_INTERFACE_DISPLAY_BLOCK; -#define _dbaselen ((size_t )&((struct dirent *)0)->d_name[0]) - -#ifdef __GLIBC__ -#define _dreclen(namlen) \ - ((_dbaselen + (namlen) + __alignof__ (struct dirent)) & \ - ~(__alignof__ (struct dirent) - 1)) -#else /* !defined(__GLIBC__) */ -#define _dreclen(namlen) \ - _rndup(_dbaselen + (namlen) + 1, sizeof(int)) -#endif - -#if defined(__GLIBC__) -#define _fast_alloc(n) alloca(n) -#define _fast_free(p) -#else /* !defined(__GLIBC__) */ -#define _fast_alloc(n) malloc(n) -#define _fast_free(p) free(p) -#endif - SYSIO_INTERFACE_ENTER; -#if defined(BSD) - if (nbytes < 0) - SYSIO_INTERFACE_RETURN(-1, -EINVAL); -#endif - - inbytes = nbytes; - if (inbytes > 8 * 1024) { - /* - * Limit stack use. - */ - inbytes = 8 * 1024; - } - ibuf = _fast_alloc(inbytes); - if (!ibuf) - SYSIO_INTERFACE_RETURN(-1, -ENOMEM); - dp = (struct dirent *)buf; - - ibase = *basep; - cc = - PREPEND(_, SYSIO_INTERFACE_NAME(getdirentries64))(fd, - ibuf, - inbytes, - &ibase); - if (cc < 0) { - cc = -errno; - goto out; - } - *basep = (off_t )ibase; - if (sizeof(*basep) != sizeof(ibase) && *basep != ibase) { - cc = -EOVERFLOW; - goto out; + fil = _sysio_fd_find(fd); + if (!(fil && fil->f_ino)) { + SYSIO_INTERFACE_RETURN(-1, -EBADF); } -#if defined(BSD) - off = *basep; -#endif - od64p = NULL; - d64p = ibuf; - for (;;) { - if (!cc) - break; -#ifdef HAVE_D_NAMLEN - n = d64p->d_namlen; -#else - n = strlen(d64p->d_name); -#endif + count = cc = filldirents(fil, buf, nbytes, &b); + d64p = (void *)buf; + dp = (void *)buf; + reclen = 0; + while (cc > 0) { + n = _namlen(d64p); reclen = _dreclen(n); - if (reclen >= (unsigned )nbytes) - break; - dp->d_ino = (ino_t )d64p->d_ino; -#if !(defined(BSD)) - dp->d_off = (off_t )d64p->d_off; -#endif - if ((sizeof(dp->d_ino) != sizeof(d64p->d_ino) && - dp->d_ino != d64p->d_ino) - || -#if !(defined(BSD)) - (sizeof(dp->d_off) != sizeof(d64p->d_off) && - dp->d_off != d64p->d_off) -#else - (off + (int )reclen < off) -#endif - ) { - cc = -EOVERFLOW; + d64.d_ino = d64p->d_ino; + d64.d_off = d64p->d_off; + d64.d_type = d64p->d_type; + d64.d_reclen = d64p->d_reclen; + /* + * Copy name first. + */ + (void )memcpy(dp->d_name, d64p->d_name, n); + /* + * Then, the rest. + */ + dp->d_ino = d64.d_ino; + dp->d_off = d64.d_off; + if (dp->d_ino != d64.d_ino || + dp->d_off != d64.d_off) { + /* + * If conversion failure then we are done. + */ + if (cc == count) { + /* + * Couldn't process any entries. We return + * the error now. + */ + cc = - EOVERFLOW; + } break; } - dp->d_type = d64p->d_type; + fil->f_pos = dp->d_off; + dp->d_type = d64.d_type; dp->d_reclen = reclen; - nxtdp = (struct dirent *)((char *)dp + dp->d_reclen); - (void )memcpy(dp->d_name, d64p->d_name, n); - for (cp = dp->d_name + n; cp < (char *)nxtdp; *cp++ = '\0') - ; - cc -= d64p->d_reclen; - od64p = d64p; - d64p = (struct dirent64 *)((char *)d64p + d64p->d_reclen); - nbytes -= reclen; -#if defined(BSD) - off += reclen; + /* + * Fill the remainder with zeros. + */ + p = (char *)dp + dp->d_reclen; +#ifdef HAVE_D_NAMLEN + dp->d_namlen = n; #endif - dp = nxtdp; + cp = dp->d_name + n; + do { + *cp++ = 0; + } while (cp < (char *)p); + /* + * Advance. + */ + dp = p; + cc -= d64.d_reclen; + d64p = (struct dirent64 *)((char *)d64p + d64.d_reclen); } -out: - _fast_free(ibuf); - - if (dp == (struct dirent *)buf && cc < 0) - SYSIO_INTERFACE_RETURN(-1, (int )cc); + if (cc < 0) + SYSIO_INTERFACE_RETURN(-1, cc); cc = (char *)dp - buf; - if (cc) - *basep = -#if !(defined(BSD)) - od64p->d_off; -#else - off; -#endif + *basep = b; SYSIO_INTERFACE_RETURN(cc, 0); - -#ifdef __GLIBC__ -#undef _fast_alloc -#undef _fast_free -#endif -#undef _dreclen -#undef _dbaselen } #else /* !defined(DIRENT64_IS_NATURAL) */ sysio_sym_strong_alias(PREPEND(_, SYSIO_INTERFACE_NAME(getdirentries64),