(linenum→info "unix/slp.c:2238")

glibc/2.7/dirent/scandir.c

    1: /* Copyright (C) 1992-1998, 2000, 2002, 2003 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3: 
    4:    The GNU C Library is free software; you can redistribute it and/or
    5:    modify it under the terms of the GNU Lesser General Public
    6:    License as published by the Free Software Foundation; either
    7:    version 2.1 of the License, or (at your option) any later version.
    8: 
    9:    The GNU C Library is distributed in the hope that it will be useful,
   10:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12:    Lesser General Public License for more details.
   13: 
   14:    You should have received a copy of the GNU Lesser General Public
   15:    License along with the GNU C Library; if not, write to the Free
   16:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   17:    02111-1307 USA.  */
   18: 
   19: #include <dirent.h>
   20: #include <stdlib.h>
   21: #include <string.h>
   22: #include <errno.h>
   23: #include <bits/libc-lock.h>
   24: 
   25: #ifndef SCANDIR
   26: #define SCANDIR scandir
   27: #define READDIR __readdir
   28: #define DIRENT_TYPE struct dirent
   29: #endif
   30: 
   31: #ifndef SCANDIR_CANCEL
   32: #define SCANDIR_CANCEL
   33: struct scandir_cancel_struct
   34: {
   35:   DIR *dp;
   36:   void *v;
   37:   size_t cnt;
   38: };
   39: 
   40: static void
   41: cancel_handler (void *arg)
   42: {
   43:   struct scandir_cancel_struct *cp = arg;
   44:   size_t i;
   45:   void **v = cp->v;
   46: 
   47:   for (i = 0; i < cp->cnt; ++i)
   48:     free (v[i]);
   49:   free (v);
   50:   (void) __closedir (cp->dp);
   51: }
   52: #endif
   53: 
   54: 
   55: int
   56: SCANDIR (dir, namelist, select, cmp)
   57:      const char *dir;
   58:      DIRENT_TYPE ***namelist;
   59:      int (*select) (const DIRENT_TYPE *);
   60:      int (*cmp) (const void *, const void *);
   61: {
   62:   DIR *dp = __opendir (dir);
   63:   DIRENT_TYPE **v = NULL;
   64:   size_t vsize = 0;
   65:   struct scandir_cancel_struct c;
   66:   DIRENT_TYPE *d;
   67:   int save;
   68: 
   69:   if (dp == NULL)
   70:     return -1;
   71: 
   72:   save = errno;
   73:   __set_errno (0);
   74: 
   75:   c.dp = dp;
   76:   c.v = NULL;
   77:   c.cnt = 0;
   78:   __libc_cleanup_push (cancel_handler, &c);
   79: 
   80:   while ((d = READDIR (dp)) != NULL)
   81:     {
   82:       int use_it = select == NULL;
   83: 
   84:       if (! use_it)
   85:         {
   86:           use_it = select (d);
   87:           /* The select function might have changed errno.  It was
   88:              zero before and it need to be again to make the latter
   89:              tests work.  */
   90:           __set_errno (0);
   91:         }
   92: 
   93:       if (use_it)
   94:         {
   95:           DIRENT_TYPE *vnew;
   96:           size_t dsize;
   97: 
   98:           /* Ignore errors from select or readdir */
   99:           __set_errno (0);
  100: 
  101:           if (__builtin_expect (c.cnt == vsize, 0))
  102:             {
  103:               DIRENT_TYPE **new;
  104:               if (vsize == 0)
  105:                 vsize = 10;
  106:               else
  107:                 vsize *= 2;
  108:               new = (DIRENT_TYPE **) realloc (v, vsize * sizeof (*v));
  109:               if (new == NULL)
  110:                 break;
  111:               v = new;
  112:               c.v = (void *) v;
  113:             }
  114: 
  115:           dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
  116:           vnew = (DIRENT_TYPE *) malloc (dsize);
  117:           if (vnew == NULL)
  118:             break;
  119: 
  120:           v[c.cnt++] = (DIRENT_TYPE *) memcpy (vnew, d, dsize);
  121:         }
  122:     }
  123: 
  124:   if (__builtin_expect (errno, 0) != 0)
  125:     {
  126:       save = errno;
  127: 
  128:       while (c.cnt > 0)
  129:         free (v[--c.cnt]);
  130:       free (v);
  131:       c.cnt = -1;
  132:     }
  133:   else
  134:     {
  135:       /* Sort the list if we have a comparison function to sort with.  */
  136:       if (cmp != NULL)
  137:         qsort (v, c.cnt, sizeof (*v), cmp);
  138: 
  139:       *namelist = v;
  140:     }
  141: 
  142:   __libc_cleanup_pop (0);
  143: 
  144:   (void) __closedir (dp);
  145:   __set_errno (save);
  146: 
  147:   return c.cnt;
  148: }
Syntax (Markdown)