⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 glob.c

📁 android-w.song.android.widget
💻 C
📖 第 1 页 / 共 2 页
字号:
      /* Scan the directory, finding all names that match.	 For each name that matches, allocate a struct globval	 on the stack and store the name in it.	 Chain those structs together; lastlink is the front of the chain.  */      while (1)	{	  /* Make globbing interruptible in the shell. */	  if (interrupt_state || terminating_signal)	    {	      lose = 1;	      break;	    }	  	  dp = readdir (d);	  if (dp == NULL)	    break;	  /* If this directory entry is not to be used, try again. */	  if (REAL_DIR_ENTRY (dp) == 0)	    continue;#if 0	  if (dp->d_name == 0 || *dp->d_name == 0)	    continue;#endif#if HANDLE_MULTIBYTE	  if (MB_CUR_MAX > 1 && mbskipname (pat, dp->d_name, flags))	    continue;	  else#endif	  if (skipname (pat, dp->d_name, flags))	    continue;	  /* If we're only interested in directories, don't bother with files */	  if (flags & (GX_MATCHDIRS|GX_ALLDIRS))	    {	      pflags = (flags & GX_ALLDIRS) ? MP_RMDOT : 0;	      if (flags & GX_NULLDIR)		pflags |= MP_IGNDOT;	      subdir = sh_makepath (dir, dp->d_name, pflags);	      isdir = glob_testdir (subdir);	      if (isdir < 0 && (flags & GX_MATCHDIRS))		{		  free (subdir);		  continue;		}	    }	  if (flags & GX_ALLDIRS)	    {	      if (isdir == 0)		{		  dirlist = finddirs (pat, subdir, (flags & ~GX_ADDCURDIR), &e, &ndirs);		  if (dirlist == &finddirs_error_return)		    {		      free (subdir);		      lose = 1;		      break;		    }		  if (ndirs)		/* add recursive directories to list */		    {		      if (firstmalloc == 0)		        firstmalloc = e;		      e->next = lastlink;		      lastlink = dirlist;		      count += ndirs;		    }		}	      nextlink = (struct globval *) malloc (sizeof (struct globval));	      if (firstmalloc == 0)		firstmalloc = nextlink;	      sdlen = strlen (subdir);	      nextname = (char *) malloc (sdlen + 1);	      if (nextlink == 0 || nextname == 0)		{		  free (subdir);		  lose = 1;		  break;		}	      nextlink->next = lastlink;	      lastlink = nextlink;	      nextlink->name = nextname;	      bcopy (subdir, nextname, sdlen + 1);	      free (subdir);	      ++count;	      continue;	    }	  convfn = fnx_fromfs (dp->d_name, D_NAMLEN (dp));	  if (strmatch (pat, convfn, mflags) != FNM_NOMATCH)	    {	      if (nalloca < ALLOCA_MAX)		{		  nextlink = (struct globval *) alloca (sizeof (struct globval));		  nalloca += sizeof (struct globval);		}	      else		{		  nextlink = (struct globval *) malloc (sizeof (struct globval));		  if (firstmalloc == 0)		    firstmalloc = nextlink;		}	      nextname = (char *) malloc (D_NAMLEN (dp) + 1);	      if (nextlink == 0 || nextname == 0)		{		  lose = 1;		  break;		}	      nextlink->next = lastlink;	      lastlink = nextlink;	      nextlink->name = nextname;	      bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);	      ++count;	    }	}      (void) closedir (d);    }  /* compat: if GX_ADDCURDIR, add the passed directory also.  Add an empty     directory name as a placeholder if GX_NULLDIR (in which case the passed     directory name is "."). */  if (add_current)    {      sdlen = strlen (dir);      nextname = (char *)malloc (sdlen + 1);      nextlink = (struct globval *) malloc (sizeof (struct globval));      if (nextlink == 0 || nextname == 0)	lose = 1;      else	{	  nextlink->name = nextname;	  nextlink->next = lastlink;	  lastlink = nextlink;	  if (flags & GX_NULLDIR)	    nextname[0] = '\0';	  else	    bcopy (dir, nextname, sdlen + 1);	  ++count;	}    }  if (lose == 0)    {      name_vector = (char **) malloc ((count + 1) * sizeof (char *));      lose |= name_vector == NULL;    }  /* Have we run out of memory?	 */  if (lose)    {      tmplink = 0;      /* Here free the strings we have got.  */      while (lastlink)	{	  /* Since we build the list in reverse order, the first N entries	     will be allocated with malloc, if firstmalloc is set, from	     lastlink to firstmalloc. */	  if (firstmalloc)	    {	      if (lastlink == firstmalloc)		firstmalloc = 0;	      tmplink = lastlink;	    }	  else	    tmplink = 0;	  free (lastlink->name);	  lastlink = lastlink->next;	  FREE (tmplink);	}      QUIT;      return ((char **)NULL);    }  /* Copy the name pointers from the linked list into the vector.  */  for (tmplink = lastlink, i = 0; i < count; ++i)    {      name_vector[i] = tmplink->name;      tmplink = tmplink->next;    }  name_vector[count] = NULL;  /* If we allocated some of the struct globvals, free them now. */  if (firstmalloc)    {      tmplink = 0;      while (lastlink)	{	  tmplink = lastlink;	  if (lastlink == firstmalloc)	    lastlink = firstmalloc = 0;	  else	    lastlink = lastlink->next;	  free (tmplink);	}    }  return (name_vector);}/* Return a new array which is the concatenation of each string in ARRAY   to DIR.  This function expects you to pass in an allocated ARRAY, and   it takes care of free()ing that array.  Thus, you might think of this   function as side-effecting ARRAY.  This should handle GX_MARKDIRS. */static char **glob_dir_to_array (dir, array, flags)     char *dir, **array;     int flags;{  register unsigned int i, l;  int add_slash;  char **result, *new;  struct stat sb;  l = strlen (dir);  if (l == 0)    {      if (flags & GX_MARKDIRS)	for (i = 0; array[i]; i++)	  {	    if ((stat (array[i], &sb) == 0) && S_ISDIR (sb.st_mode))	      {		l = strlen (array[i]);		new = (char *)realloc (array[i], l + 2);		if (new == 0)		  return NULL;		new[l] = '/';		new[l+1] = '\0';		array[i] = new;	      }	  }      return (array);    }  add_slash = dir[l - 1] != '/';  i = 0;  while (array[i] != NULL)    ++i;  result = (char **) malloc ((i + 1) * sizeof (char *));  if (result == NULL)    return (NULL);  for (i = 0; array[i] != NULL; i++)    {      /* 3 == 1 for NUL, 1 for slash at end of DIR, 1 for GX_MARKDIRS */      result[i] = (char *) malloc (l + strlen (array[i]) + 3);      if (result[i] == NULL)	return (NULL);      strcpy (result[i], dir);      if (add_slash)	result[i][l] = '/';      strcpy (result[i] + l + add_slash, array[i]);      if (flags & GX_MARKDIRS)	{	  if ((stat (result[i], &sb) == 0) && S_ISDIR (sb.st_mode))	    {	      size_t rlen;	      rlen = strlen (result[i]);	      result[i][rlen] = '/';	      result[i][rlen+1] = '\0';	    }	}    }  result[i] = NULL;  /* Free the input array.  */  for (i = 0; array[i] != NULL; i++)    free (array[i]);  free ((char *) array);  return (result);}/* Do globbing on PATHNAME.  Return an array of pathnames that match,   marking the end of the array with a null-pointer as an element.   If no pathnames match, then the array is empty (first element is null).   If there isn't enough memory, then return NULL.   If a file system error occurs, return -1; `errno' has the error code.  */char **glob_filename (pathname, flags)     char *pathname;     int flags;{  char **result;  unsigned int result_size;  char *directory_name, *filename, *dname;  unsigned int directory_len;  int free_dirname;			/* flag */  int dflags;  result = (char **) malloc (sizeof (char *));  result_size = 1;  if (result == NULL)    return (NULL);  result[0] = NULL;  directory_name = NULL;  /* Find the filename.  */  filename = strrchr (pathname, '/');  if (filename == NULL)    {      filename = pathname;      directory_name = "";      directory_len = 0;      free_dirname = 0;    }  else    {      directory_len = (filename - pathname) + 1;      directory_name = (char *) malloc (directory_len + 1);      if (directory_name == 0)		/* allocation failed? */	return (NULL);      bcopy (pathname, directory_name, directory_len);      directory_name[directory_len] = '\0';      ++filename;      free_dirname = 1;    }  /* If directory_name contains globbing characters, then we     have to expand the previous levels.  Just recurse. */  if (glob_pattern_p (directory_name))    {      char **directories;      register unsigned int i;      dflags = flags & ~GX_MARKDIRS;      if ((flags & GX_GLOBSTAR) && directory_name[0] == '*' && directory_name[1] == '*' && (directory_name[2] == '/' || directory_name[2] == '\0'))	dflags |= GX_ALLDIRS|GX_ADDCURDIR;      if (directory_name[directory_len - 1] == '/')	directory_name[directory_len - 1] = '\0';      directories = glob_filename (directory_name, dflags);      if (free_dirname)	{	  free (directory_name);	  directory_name = NULL;	}      if (directories == NULL)	goto memory_error;      else if (directories == (char **)&glob_error_return)	{	  free ((char *) result);	  return ((char **) &glob_error_return);	}      else if (*directories == NULL)	{	  free ((char *) directories);	  free ((char *) result);	  return ((char **) &glob_error_return);	}      /* We have successfully globbed the preceding directory name.	 For each name in DIRECTORIES, call glob_vector on it and	 FILENAME.  Concatenate the results together.  */      for (i = 0; directories[i] != NULL; ++i)	{	  char **temp_results;	  /* XXX -- we've recursively scanned any directories resulting from	     a `**', so turn off the flag.  We turn it on again below if	     filename is `**' */	  /* Scan directory even on a NULL filename.  That way, `*h/'	     returns only directories ending in `h', instead of all	     files ending in `h' with a `/' appended. */	  dname = directories[i];	  dflags = flags & ~(GX_MARKDIRS|GX_ALLDIRS|GX_ADDCURDIR);	  if ((flags & GX_GLOBSTAR) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')	    dflags |= GX_ALLDIRS|GX_ADDCURDIR;	  if (dname[0] == '\0' && filename[0])	    {	      dflags |= GX_NULLDIR;	      dname = ".";	/* treat null directory name and non-null filename as current directory */	    }	  temp_results = glob_vector (filename, dname, dflags);	  /* Handle error cases. */	  if (temp_results == NULL)	    goto memory_error;	  else if (temp_results == (char **)&glob_error_return)	    /* This filename is probably not a directory.  Ignore it.  */	    ;	  else	    {	      char **array;	      register unsigned int l;	      /* If we're expanding **, we don't need to glue the directory		 name to the results; we've already done it in glob_vector */	      if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')		array = temp_results;	      else		array = glob_dir_to_array (directories[i], temp_results, flags);	      l = 0;	      while (array[l] != NULL)		++l;	      result =		(char **)realloc (result, (result_size + l) * sizeof (char *));	      if (result == NULL)		goto memory_error;	      for (l = 0; array[l] != NULL; ++l)		result[result_size++ - 1] = array[l];	      result[result_size - 1] = NULL;	      /* Note that the elements of ARRAY are not freed.  */	      if (array != temp_results)		free ((char *) array);	    }	}      /* Free the directories.  */      for (i = 0; directories[i]; i++)	free (directories[i]);      free ((char *) directories);      return (result);    }  /* If there is only a directory name, return it. */  if (*filename == '\0')    {      result = (char **) realloc ((char *) result, 2 * sizeof (char *));      if (result == NULL)	return (NULL);      /* Handle GX_MARKDIRS here. */      result[0] = (char *) malloc (directory_len + 1);      if (result[0] == NULL)	goto memory_error;      bcopy (directory_name, result[0], directory_len + 1);      if (free_dirname)	free (directory_name);      result[1] = NULL;      return (result);    }  else    {      char **temp_results;      /* There are no unquoted globbing characters in DIRECTORY_NAME.	 Dequote it before we try to open the directory since there may	 be quoted globbing characters which should be treated verbatim. */      if (directory_len > 0)	dequote_pathname (directory_name);      /* We allocated a small array called RESULT, which we won't be using.	 Free that memory now. */      free (result);      /* Just return what glob_vector () returns appended to the	 directory name. */      /* If flags & GX_ALLDIRS, we're called recursively */      dflags = flags & ~GX_MARKDIRS;      if (directory_len == 0)	dflags |= GX_NULLDIR;      if ((flags & GX_GLOBSTAR) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')	{	  dflags |= GX_ALLDIRS|GX_ADDCURDIR;#if 0	  /* If we want all directories (dflags & GX_ALLDIRS) and we're not	     being called recursively as something like `echo [star][star]/[star].o'	     ((flags & GX_ALLDIRS) == 0), we want to prevent glob_vector from	     adding a null directory name to the front of the temp_results	     array.  We turn off ADDCURDIR if not called recursively and	     dlen == 0 */#endif	  if (directory_len == 0 && (flags & GX_ALLDIRS) == 0)	    dflags &= ~GX_ADDCURDIR;	}      temp_results = glob_vector (filename,				  (directory_len == 0 ? "." : directory_name),				  dflags);      if (temp_results == NULL || temp_results == (char **)&glob_error_return)	{	  if (free_dirname)	    free (directory_name);	  return (temp_results);	}      result = glob_dir_to_array ((dflags & GX_ALLDIRS) ? "" : directory_name, temp_results, flags);      if (free_dirname)	free (directory_name);      return (result);    }  /* We get to memory_error if the program has run out of memory, or     if this is the shell, and we have been interrupted. */ memory_error:  if (result != NULL)    {      register unsigned int i;      for (i = 0; result[i] != NULL; ++i)	free (result[i]);      free ((char *) result);    }  if (free_dirname && directory_name)    free (directory_name);  QUIT;  return (NULL);}#if defined (TEST)main (argc, argv)     int argc;     char **argv;{  unsigned int i;  for (i = 1; i < argc; ++i)    {      char **value = glob_filename (argv[i], 0);      if (value == NULL)	puts ("Out of memory.");      else if (value == &glob_error_return)	perror (argv[i]);      else	for (i = 0; value[i] != NULL; i++)	  puts (value[i]);    }  exit (0);}#endif	/* TEST.  */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -