| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 | /* Test glob memory management.   for the filesystem access functions.   Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.   This file is part of the GNU C Library.   The GNU C 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   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307 USA.  */#include <errno.h>#include <error.h>#include <dirent.h>#include <glob.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/stat.h>// #define DEBUG#ifdef DEBUG# define PRINTF(fmt, args...) \  do					\    {					\      int save_errno = errno;		\      printf (fmt, ##args);		\      errno = save_errno;		\    } while (0)#else# define PRINTF(fmt, args...)#endif#ifdef GLOB_ALTDIRFUNCstatic struct{  const char *name;  int level;  int type;  mode_t mode;} filesystem[] ={  { ".", 1, DT_DIR, 0755 },  { "..", 1, DT_DIR, 0755 },  { "dir", 1, DT_DIR, 0755 },    { ".", 2, DT_DIR, 0755 },    { "..", 2, DT_DIR, 0755 },    { "readable", 2, DT_DIR, 0755 },      { ".", 3, DT_DIR, 0755 },      { "..", 3, DT_DIR, 0755 },      { "a", 3, DT_REG, 0644 },    { "unreadable", 2, DT_DIR, 0111 },      { ".", 3, DT_DIR, 0111 },      { "..", 3, DT_DIR, 0755 },      { "a", 3, DT_REG, 0644 },    { "zz-readable", 2, DT_DIR, 0755 },      { ".", 3, DT_DIR, 0755 },      { "..", 3, DT_DIR, 0755 },      { "a", 3, DT_REG, 0644 }};#define nfiles (sizeof (filesystem) / sizeof (filesystem[0]))typedef struct{  int level;  int idx;  struct dirent d;  char room_for_dirent[NAME_MAX];} my_DIR;static long intfind_file (const char *s){  int level = 1;  long int idx = 0;  if (strcmp (s, ".") == 0)    return 0;  if (s[0] == '.' && s[1] == '/')    s += 2;  while (*s != '\0')    {      char *endp = strchrnul (s, '/');      PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level);      while (idx < nfiles && filesystem[idx].level >= level)	{	  if (filesystem[idx].level == level	      && memcmp (s, filesystem[idx].name, endp - s) == 0	      && filesystem[idx].name[endp - s] == '\0')	    break;	  ++idx;	}      if (idx == nfiles || filesystem[idx].level < level)	{	  errno = ENOENT;	  return -1;	}      if (*endp == '\0')	return idx + 1;      if (filesystem[idx].type != DT_DIR	  && (idx + 1 >= nfiles	      || filesystem[idx].level >= filesystem[idx + 1].level))	{	  errno = ENOTDIR;	  return -1;	}      ++idx;      s = endp + 1;      ++level;    }  errno = ENOENT;  return -1;}static void *my_opendir (const char *s){  long int idx = find_file (s);  my_DIR *dir;  if (idx == -1)    {      PRINTF ("my_opendir(\"%s\") == NULL (%m)\n", s);      return NULL;    }  if ((filesystem[idx].mode & 0400) == 0)    {      errno = EACCES;      PRINTF ("my_opendir(\"%s\") == NULL (%m)\n", s);      return NULL;    }  dir = (my_DIR *) malloc (sizeof (my_DIR));  if (dir == NULL)    {      printf ("cannot allocate directory handle: %m\n");      exit (EXIT_FAILURE);    }  dir->level = filesystem[idx].level;  dir->idx = idx;  PRINTF ("my_opendir(\"%s\") == { level: %d, idx: %ld }\n",	  s, filesystem[idx].level, idx);  return dir;}static struct dirent *my_readdir (void *gdir){  my_DIR *dir = gdir;  if (dir->idx == -1)    {      PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",	      dir->level, (long int) dir->idx);      return NULL;    }  while (dir->idx < nfiles && filesystem[dir->idx].level > dir->level)    ++dir->idx;  if (dir->idx == nfiles || filesystem[dir->idx].level < dir->level)    {      dir->idx = -1;      PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",	      dir->level, (long int) dir->idx);      return NULL;    }  dir->d.d_ino = dir->idx;#ifdef _DIRENT_HAVE_D_TYPE  dir->d.d_type = filesystem[dir->idx].type;#endif  strcpy (dir->d.d_name, filesystem[dir->idx].name);#ifdef _DIRENT_HAVE_D_TYPE  PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_type: %d, d_name: \"%s\" }\n",	  dir->level, (long int) dir->idx, dir->d.d_ino, dir->d.d_type,	  dir->d.d_name);#else  PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_name: \"%s\" }\n",	  dir->level, (long int) dir->idx, dir->d.d_ino,	  dir->d.d_name);#endif  ++dir->idx;  return &dir->d;}static voidmy_closedir (void *dir){  PRINTF ("my_closedir ()\n");  free (dir);}/* We use this function for lstat as well since we don't have any.  */static intmy_stat (const char *name, struct stat *st){  long int idx = find_file (name);  if (idx == -1)    {      PRINTF ("my_stat (\"%s\", ...) = -1 (%m)\n", name);      return -1;    }  memset (st, '\0', sizeof (*st));  if (filesystem[idx].type == DT_UNKNOWN)    st->st_mode = DTTOIF (idx + 1 < nfiles			  && filesystem[idx].level < filesystem[idx + 1].level			  ? DT_DIR : DT_REG) | filesystem[idx].mode;  else    st->st_mode = DTTOIF (filesystem[idx].type) | filesystem[idx].mode;  PRINTF ("my_stat (\"%s\", { st_mode: %o }) = 0\n", name, st->st_mode);  return 0;}static voidinit_glob_altdirfuncs (glob_t *pglob){  pglob->gl_closedir = my_closedir;  pglob->gl_readdir = my_readdir;  pglob->gl_opendir = my_opendir;  pglob->gl_lstat = my_stat;  pglob->gl_stat = my_stat;}intdo_test (void){  glob_t gl;  memset (&gl, 0, sizeof (gl));  init_glob_altdirfuncs (&gl);  if (glob ("dir/*able/*", GLOB_ERR | GLOB_ALTDIRFUNC, NULL, &gl)      != GLOB_ABORTED)    {      puts ("glob did not fail with GLOB_ABORTED");      exit (EXIT_FAILURE);     }  globfree (&gl);  memset (&gl, 0, sizeof (gl));  init_glob_altdirfuncs (&gl);  gl.gl_offs = 3;  if (glob ("dir2/*", GLOB_DOOFFS, NULL, &gl) != GLOB_NOMATCH)    {      puts ("glob did not fail with GLOB_NOMATCH");      exit (EXIT_FAILURE);     }  globfree (&gl);  return 0;}#elseint do_test (void) { return 0; }#endif#define TEST_FUNCTION do_test ()#include "../test-skeleton.c"
 |