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

glibc/2.7/posix/bug-glob2.c

    1: /* Test glob memory management.
    2:    for the filesystem access functions.
    3:    Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
    4:    This file is part of the GNU C Library.
    5: 
    6:    The GNU C Library is free software; you can redistribute it and/or
    7:    modify it under the terms of the GNU Lesser General Public
    8:    License as published by the Free Software Foundation; either
    9:    version 2.1 of the License, or (at your option) any later version.
   10: 
   11:    The GNU C Library is distributed in the hope that it will be useful,
   12:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:    Lesser General Public License for more details.
   15: 
   16:    You should have received a copy of the GNU Lesser General Public
   17:    License along with the GNU C Library; if not, write to the Free
   18:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   19:    02111-1307 USA.  */
   20: 
   21: #include <errno.h>
   22: #include <error.h>
   23: #include <dirent.h>
   24: #include <glob.h>
   25: #include <mcheck.h>
   26: #include <stdlib.h>
   27: #include <stdio.h>
   28: #include <string.h>
   29: #include <sys/stat.h>
   30: 
   31: // #define DEBUG
   32: #ifdef DEBUG
   33: # define PRINTF(fmt, args...) \
   34:   do                                    \
   35:     {                                   \
   36:       int save_errno = errno;           \
   37:       printf (fmt, ##args);             \
   38:       errno = save_errno;               \
   39:     } while (0)
   40: #else
   41: # define PRINTF(fmt, args...)
   42: #endif
   43: 
   44: 
   45: static struct
   46: {
   47:   const char *name;
   48:   int level;
   49:   int type;
   50:   mode_t mode;
   51: } filesystem[] =
   52: {
   53:   { ".", 1, DT_DIR, 0755 },
   54:   { "..", 1, DT_DIR, 0755 },
   55:   { "dir", 1, DT_DIR, 0755 },
   56:     { ".", 2, DT_DIR, 0755 },
   57:     { "..", 2, DT_DIR, 0755 },
   58:     { "readable", 2, DT_DIR, 0755 },
   59:       { ".", 3, DT_DIR, 0755 },
   60:       { "..", 3, DT_DIR, 0755 },
   61:       { "a", 3, DT_REG, 0644 },
   62:     { "unreadable", 2, DT_DIR, 0111 },
   63:       { ".", 3, DT_DIR, 0111 },
   64:       { "..", 3, DT_DIR, 0755 },
   65:       { "a", 3, DT_REG, 0644 },
   66:     { "zz-readable", 2, DT_DIR, 0755 },
   67:       { ".", 3, DT_DIR, 0755 },
   68:       { "..", 3, DT_DIR, 0755 },
   69:       { "a", 3, DT_REG, 0644 }
   70: };
   71: #define nfiles (sizeof (filesystem) / sizeof (filesystem[0]))
   72: 
   73: 
   74: typedef struct
   75: {
   76:   int level;
   77:   int idx;
   78:   struct dirent d;
   79:   char room_for_dirent[NAME_MAX];
   80: } my_DIR;
   81: 
   82: 
   83: static long int
   84: find_file (const char *s)
   85: {
   86:   int level = 1;
   87:   long int idx = 0;
   88: 
   89:   if (strcmp (s, ".") == 0)
   90:     return 0;
   91: 
   92:   if (s[0] == '.' && s[1] == '/')
   93:     s += 2;
   94: 
   95:   while (*s != '\0')
   96:     {
   97:       char *endp = strchrnul (s, '/');
   98: 
   99:       PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level);
  100: 
  101:       while (idx < nfiles && filesystem[idx].level >= level)
  102:         {
  103:           if (filesystem[idx].level == level
  104:               && memcmp (s, filesystem[idx].name, endp - s) == 0
  105:               && filesystem[idx].name[endp - s] == '\0')
  106:             break;
  107:           ++idx;
  108:         }
  109: 
  110:       if (idx == nfiles || filesystem[idx].level < level)
  111:         {
  112:           errno = ENOENT;
  113:           return -1;
  114:         }
  115: 
  116:       if (*endp == '\0')
  117:         return idx + 1;
  118: 
  119:       if (filesystem[idx].type != DT_DIR
  120:           && (idx + 1 >= nfiles
  121:               || filesystem[idx].level >= filesystem[idx + 1].level))
  122:         {
  123:           errno = ENOTDIR;
  124:           return -1;
  125:         }
  126: 
  127:       ++idx;
  128: 
  129:       s = endp + 1;
  130:       ++level;
  131:     }
  132: 
  133:   errno = ENOENT;
  134:   return -1;
  135: }
  136: 
  137: 
  138: static void *
  139: my_opendir (const char *s)
  140: {
  141:   long int idx = find_file (s);
  142:   my_DIR *dir;
  143: 
  144:   if (idx == -1)
  145:     {
  146:       PRINTF ("my_opendir(\"%s\") == NULL (%m)\n", s);
  147:       return NULL;
  148:     }
  149: 
  150:   if ((filesystem[idx].mode & 0400) == 0)
  151:     {
  152:       errno = EACCES;
  153:       PRINTF ("my_opendir(\"%s\") == NULL (%m)\n", s);
  154:       return NULL;
  155:     }
  156: 
  157:   dir = (my_DIR *) malloc (sizeof (my_DIR));
  158:   if (dir == NULL)
  159:     {
  160:       printf ("cannot allocate directory handle: %m\n");
  161:       exit (EXIT_FAILURE);
  162:     }
  163: 
  164:   dir->level = filesystem[idx].level;
  165:   dir->idx = idx;
  166: 
  167:   PRINTF ("my_opendir(\"%s\") == { level: %d, idx: %ld }\n",
  168:           s, filesystem[idx].level, idx);
  169: 
  170:   return dir;
  171: }
  172: 
  173: 
  174: static struct dirent *
  175: my_readdir (void *gdir)
  176: {
  177:   my_DIR *dir = gdir;
  178: 
  179:   if (dir->idx == -1)
  180:     {
  181:       PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",
  182:               dir->level, (long int) dir->idx);
  183:       return NULL;
  184:     }
  185: 
  186:   while (dir->idx < nfiles && filesystem[dir->idx].level > dir->level)
  187:     ++dir->idx;
  188: 
  189:   if (dir->idx == nfiles || filesystem[dir->idx].level < dir->level)
  190:     {
  191:       dir->idx = -1;
  192:       PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",
  193:               dir->level, (long int) dir->idx);
  194:       return NULL;
  195:     }
  196: 
  197:   dir->d.d_ino = dir->idx;
  198: 
  199: #ifdef _DIRENT_HAVE_D_TYPE
  200:   dir->d.d_type = filesystem[dir->idx].type;
  201: #endif
  202: 
  203:   strcpy (dir->d.d_name, filesystem[dir->idx].name);
  204: 
  205: #ifdef _DIRENT_HAVE_D_TYPE
  206:   PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_type: %d, d_name: \"%s\" }\n",
  207:           dir->level, (long int) dir->idx, dir->d.d_ino, dir->d.d_type,
  208:           dir->d.d_name);
  209: #else
  210:   PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_name: \"%s\" }\n",
  211:           dir->level, (long int) dir->idx, dir->d.d_ino,
  212:           dir->d.d_name);
  213: #endif
  214: 
  215:   ++dir->idx;
  216: 
  217:   return &dir->d;
  218: }
  219: 
  220: 
  221: static void
  222: my_closedir (void *dir)
  223: {
  224:   PRINTF ("my_closedir ()\n");
  225:   free (dir);
  226: }
  227: 
  228: 
  229: /* We use this function for lstat as well since we don't have any.  */
  230: static int
  231: my_stat (const char *name, struct stat *st)
  232: {
  233:   long int idx = find_file (name);
  234: 
  235:   if (idx == -1)
  236:     {
  237:       PRINTF ("my_stat (\"%s\", ...) = -1 (%m)\n", name);
  238:       return -1;
  239:     }
  240: 
  241:   memset (st, '\0', sizeof (*st));
  242: 
  243:   if (filesystem[idx].type == DT_UNKNOWN)
  244:     st->st_mode = DTTOIF (idx + 1 < nfiles
  245:                           && filesystem[idx].level < filesystem[idx + 1].level
  246:                           ? DT_DIR : DT_REG) | filesystem[idx].mode;
  247:   else
  248:     st->st_mode = DTTOIF (filesystem[idx].type) | filesystem[idx].mode;
  249: 
  250:   PRINTF ("my_stat (\"%s\", { st_mode: %o }) = 0\n", name, st->st_mode);
  251: 
  252:   return 0;
  253: }
  254: 
  255: 
  256: static void
  257: init_glob_altdirfuncs (glob_t *pglob)
  258: {
  259:   pglob->gl_closedir = my_closedir;
  260:   pglob->gl_readdir = my_readdir;
  261:   pglob->gl_opendir = my_opendir;
  262:   pglob->gl_lstat = my_stat;
  263:   pglob->gl_stat = my_stat;
  264: }
  265: 
  266: 
  267: int
  268: do_test (void)
  269: {
  270:   mtrace ();
  271: 
  272:   glob_t gl;
  273:   memset (&gl, 0, sizeof (gl));
  274:   init_glob_altdirfuncs (&gl);
  275: 
  276:   if (glob ("dir/*able/*", GLOB_ERR | GLOB_ALTDIRFUNC, NULL, &gl)
  277:       != GLOB_ABORTED)
  278:     {
  279:       puts ("glob did not fail with GLOB_ABORTED");
  280:       exit (EXIT_FAILURE); 
  281:     }
  282: 
  283:   globfree (&gl);
  284: 
  285:   memset (&gl, 0, sizeof (gl));
  286:   init_glob_altdirfuncs (&gl);
  287: 
  288:   gl.gl_offs = 3;
  289:   if (glob ("dir2/*", GLOB_DOOFFS, NULL, &gl) != GLOB_NOMATCH)
  290:     {
  291:       puts ("glob did not fail with GLOB_NOMATCH");
  292:       exit (EXIT_FAILURE); 
  293:     }
  294: 
  295:   globfree (&gl);
  296: 
  297:   muntrace ();
  298: 
  299:   return 0;
  300: }
  301: 
  302: #define TEST_FUNCTION do_test ()
  303: #include "../test-skeleton.c"
Syntax (Markdown)