]>
git.ipfire.org Git - thirdparty/bash.git/blob - lib/glob/glob.c
1 /* File-name wildcard pattern matching for GNU.
2 Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program 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
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
18 /* To whomever it may concern: I have never seen the code which most
19 Unix programs use to perform this function. I wrote this from scratch
20 based on specifications for the pattern matching. --RMS. */
24 #if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
26 #endif /* _AIX && RISC6000 && !__GNUC__ */
29 # include "bashtypes.h"
31 # include <sys/types.h>
34 #if defined (HAVE_UNISTD_H)
39 # include "bashansi.h"
41 # if defined (HAVE_STDLIB_H)
44 # if defined (HAVE_STRING_H)
46 # else /* !HAVE_STRING_H */
48 # endif /* !HAVE_STRING_H */
51 #if defined (HAVE_DIRENT_H)
53 # define D_NAMLEN(d) strlen ((d)->d_name)
54 #else /* !HAVE_DIRENT_H */
55 # define D_NAMLEN(d) ((d)->d_namlen)
56 # if defined (HAVE_SYS_NDIR_H)
57 # include <sys/ndir.h>
59 # if defined (HAVE_SYS_DIR_H)
61 # endif /* HAVE_SYS_DIR_H */
62 # if defined (HAVE_NDIR_H)
65 # if !defined (dirent)
66 # define dirent direct
68 #endif /* !HAVE_DIRENT_H */
70 #if defined (_POSIX_SOURCE) && !defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO)
71 /* Posix does not require that the d_ino field be present, and some
72 systems do not provide it. */
73 # define REAL_DIR_ENTRY(dp) 1
75 # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
76 #endif /* _POSIX_SOURCE */
78 #if !defined (HAVE_BCOPY) && !defined (bcopy)
79 # define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
80 #endif /* !HAVE_BCOPY && !bcopy */
83 # include "posixstat.h"
85 # include <sys/stat.h>
94 # include "memalloc.h"
99 #if !defined (HAVE_STDLIB_H) && !defined (SHELL)
100 extern char *malloc (), *realloc ();
102 #endif /* !HAVE_STDLIB_H */
105 # if defined (__STDC__)
106 # define NULL ((void *) 0)
109 # endif /* __STDC__ */
113 extern void throw_to_top_level ();
114 extern int test_eaccess ();
116 extern int interrupt_state
;
117 extern int extended_glob
;
120 /* Global variable which controls whether or not * matches .*.
121 Non-zero means don't match .*. */
122 int noglob_dot_filenames
= 1;
124 /* Global variable which controls whether or not filename globbing
125 is done without regard to case. */
126 int glob_ignore_case
= 0;
128 /* Global variable to return to signify an error in globbing. */
129 char *glob_error_return
;
131 /* Return nonzero if PATTERN has any special globbing chars in it. */
133 glob_pattern_p (pattern
)
136 register const char *p
;
143 while ((c
= *p
++) != '\0')
150 case '[': /* Only accept an open brace if there is a close */
151 bopen
++; /* brace to match it. Bracket expressions must be */
152 continue; /* complete, according to Posix.2 */
158 case '+': /* extended matching operators */
161 if (*p
== '(') /*) */
173 /* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
175 dequote_pathname (pathname
)
180 for (i
= j
= 0; pathname
&& pathname
[i
]; )
182 if (pathname
[i
] == '\\')
185 pathname
[j
++] = pathname
[i
++];
187 if (!pathname
[i
- 1])
195 /* Test whether NAME exists. */
197 #if defined (HAVE_LSTAT)
198 # define GLOB_TESTNAME(name) (lstat (name, &finfo))
199 #else /* !HAVE_LSTAT */
200 # if defined (SHELL) && !defined (AFS)
201 # define GLOB_TESTNAME(name) (test_eaccess (nextname, F_OK))
202 # else /* !SHELL || AFS */
203 # define GLOB_TESTNAME(name) (access (nextname, F_OK))
204 # endif /* !SHELL || AFS */
205 #endif /* !HAVE_LSTAT */
207 /* Return 0 if DIR is a directory, -1 otherwise. */
214 if (stat (dir
, &finfo
) < 0)
217 if (S_ISDIR (finfo
.st_mode
) == 0)
223 /* Return a vector of names of files in directory DIR
224 whose names match glob pattern PAT.
225 The names are not in any particular order.
226 Wildcards at the beginning of PAT do not match an initial period.
228 The vector is terminated by an element that is a null pointer.
230 To free the space allocated, first free the vector's elements,
231 then free the vector.
233 Return 0 if cannot get enough memory to hold the pointer
236 Return -1 if cannot access directory DIR.
237 Look in errno for more information. */
240 glob_vector (pat
, dir
)
246 struct globval
*next
;
251 register struct dirent
*dp
;
252 struct globval
*lastlink
;
253 register struct globval
*nextlink
;
254 register char *nextname
, *npat
;
257 register char **name_vector
;
258 register unsigned int i
;
259 int flags
; /* Flags passed to strmatch (). */
262 count
= lose
= skip
= 0;
264 /* If PAT is empty, skip the loop, but return one (empty) filename. */
265 if (pat
== 0 || *pat
== '\0')
267 if (glob_testdir (dir
) < 0)
268 return ((char **) &glob_error_return
);
270 nextlink
= (struct globval
*)alloca (sizeof (struct globval
));
271 nextlink
->next
= (struct globval
*)0;
272 nextname
= (char *) malloc (1);
278 nextlink
->name
= nextname
;
286 /* If the filename pattern (PAT) does not contain any globbing characters,
287 we can dispense with reading the directory, and just see if there is
288 a filename `DIR/PAT'. If there is, and we can access it, just make the
289 vector to return and bail immediately. */
290 if (skip
== 0 && glob_pattern_p (pat
) == 0)
295 if (glob_testdir (dir
) < 0)
296 return ((char **) &glob_error_return
);
298 dirlen
= strlen (dir
);
299 nextname
= (char *)malloc (dirlen
+ strlen (pat
) + 2);
300 npat
= (char *)malloc (strlen (pat
) + 1);
301 if (nextname
== 0 || npat
== 0)
306 dequote_pathname (npat
);
308 strcpy (nextname
, dir
);
309 nextname
[dirlen
++] = '/';
310 strcpy (nextname
+ dirlen
, npat
);
312 if (GLOB_TESTNAME (nextname
) >= 0)
315 nextlink
= (struct globval
*)alloca (sizeof (struct globval
));
316 nextlink
->next
= (struct globval
*)0;
318 nextlink
->name
= npat
;
333 /* Open the directory, punting immediately if we cannot. If opendir
334 is not robust (i.e., it opens non-directories successfully), test
335 that DIR is a directory and punt if it's not. */
336 #if defined (OPENDIR_NOT_ROBUST)
337 if (glob_testdir (dir
) < 0)
338 return ((char **) &glob_error_return
);
343 return ((char **) &glob_error_return
);
345 /* Compute the flags that will be passed to strmatch(). We don't
346 need to do this every time through the loop. */
347 flags
= (noglob_dot_filenames
? FNM_PERIOD
: 0) | FNM_PATHNAME
;
350 if (glob_ignore_case
)
351 flags
|= FNM_CASEFOLD
;
356 flags
|= FNM_EXTMATCH
;
359 /* Scan the directory, finding all names that match.
360 For each name that matches, allocate a struct globval
361 on the stack and store the name in it.
362 Chain those structs together; lastlink is the front of the chain. */
366 /* Make globbing interruptible in the shell. */
378 /* If this directory entry is not to be used, try again. */
379 if (REAL_DIR_ENTRY (dp
) == 0)
382 /* If a leading dot need not be explicitly matched, and the pattern
383 doesn't start with a `.', don't match `.' or `..' */
384 #define dname dp->d_name
385 if (noglob_dot_filenames
== 0 && pat
[0] != '.' &&
386 (pat
[0] != '\\' || pat
[1] != '.') &&
388 (dname
[1] == '\0' || (dname
[1] == '.' && dname
[2] == '\0'))))
392 /* If a dot must be explicity matched, check to see if they do. */
393 if (noglob_dot_filenames
&& dp
->d_name
[0] == '.' && pat
[0] != '.' &&
394 (pat
[0] != '\\' || pat
[1] != '.'))
397 if (strmatch (pat
, dp
->d_name
, flags
) != FNM_NOMATCH
)
399 nextlink
= (struct globval
*) alloca (sizeof (struct globval
));
400 nextlink
->next
= lastlink
;
401 nextname
= (char *) malloc (D_NAMLEN (dp
) + 1);
402 if (nextname
== NULL
)
408 nextlink
->name
= nextname
;
409 bcopy (dp
->d_name
, nextname
, D_NAMLEN (dp
) + 1);
419 name_vector
= (char **) malloc ((count
+ 1) * sizeof (char *));
420 lose
|= name_vector
== NULL
;
423 /* Have we run out of memory? */
426 /* Here free the strings we have got. */
429 free (lastlink
->name
);
430 lastlink
= lastlink
->next
;
434 throw_to_top_level ();
437 return ((char **)NULL
);
440 /* Copy the name pointers from the linked list into the vector. */
441 for (i
= 0; i
< count
; ++i
)
443 name_vector
[i
] = lastlink
->name
;
444 lastlink
= lastlink
->next
;
447 name_vector
[count
] = NULL
;
448 return (name_vector
);
451 /* Return a new array which is the concatenation of each string in ARRAY
452 to DIR. This function expects you to pass in an allocated ARRAY, and
453 it takes care of free()ing that array. Thus, you might think of this
454 function as side-effecting ARRAY. */
456 glob_dir_to_array (dir
, array
)
459 register unsigned int i
, l
;
467 add_slash
= dir
[l
- 1] != '/';
470 while (array
[i
] != NULL
)
473 result
= (char **) malloc ((i
+ 1) * sizeof (char *));
477 for (i
= 0; array
[i
] != NULL
; i
++)
479 result
[i
] = (char *) malloc (l
+ (add_slash
? 1 : 0)
480 + strlen (array
[i
]) + 1);
481 if (result
[i
] == NULL
)
484 strcpy (result
[i
], dir
);
487 strcpy (result
[i
] + l
+ add_slash
, array
[i
]);
491 /* Free the input array. */
492 for (i
= 0; array
[i
] != NULL
; i
++)
494 free ((char *) array
);
499 /* Do globbing on PATHNAME. Return an array of pathnames that match,
500 marking the end of the array with a null-pointer as an element.
501 If no pathnames match, then the array is empty (first element is null).
502 If there isn't enough memory, then return NULL.
503 If a file system error occurs, return -1; `errno' has the error code. */
505 glob_filename (pathname
)
509 unsigned int result_size
;
510 char *directory_name
, *filename
;
511 unsigned int directory_len
;
513 result
= (char **) malloc (sizeof (char *));
520 /* Find the filename. */
521 filename
= strrchr (pathname
, '/');
522 if (filename
== NULL
)
530 directory_len
= (filename
- pathname
) + 1;
531 directory_name
= (char *) alloca (directory_len
+ 1);
533 bcopy (pathname
, directory_name
, directory_len
);
534 directory_name
[directory_len
] = '\0';
538 /* If directory_name contains globbing characters, then we
539 have to expand the previous levels. Just recurse. */
540 if (glob_pattern_p (directory_name
))
543 register unsigned int i
;
545 if (directory_name
[directory_len
- 1] == '/')
546 directory_name
[directory_len
- 1] = '\0';
548 directories
= glob_filename (directory_name
);
550 if (directories
== NULL
)
552 else if (directories
== (char **)&glob_error_return
)
554 free ((char *) result
);
555 return ((char **) &glob_error_return
);
557 else if (*directories
== NULL
)
559 free ((char *) directories
);
560 free ((char *) result
);
561 return ((char **) &glob_error_return
);
564 /* We have successfully globbed the preceding directory name.
565 For each name in DIRECTORIES, call glob_vector on it and
566 FILENAME. Concatenate the results together. */
567 for (i
= 0; directories
[i
] != NULL
; ++i
)
571 /* Scan directory even on a NULL pathname. That way, `*h/'
572 returns only directories ending in `h', instead of all
573 files ending in `h' with a `/' appended. */
574 temp_results
= glob_vector (filename
, directories
[i
]);
576 /* Handle error cases. */
577 if (temp_results
== NULL
)
579 else if (temp_results
== (char **)&glob_error_return
)
580 /* This filename is probably not a directory. Ignore it. */
585 register unsigned int l
;
587 array
= glob_dir_to_array (directories
[i
], temp_results
);
589 while (array
[l
] != NULL
)
593 (char **)realloc (result
, (result_size
+ l
) * sizeof (char *));
598 for (l
= 0; array
[l
] != NULL
; ++l
)
599 result
[result_size
++ - 1] = array
[l
];
601 result
[result_size
- 1] = NULL
;
603 /* Note that the elements of ARRAY are not freed. */
604 free ((char *) array
);
607 /* Free the directories. */
608 for (i
= 0; directories
[i
]; i
++)
609 free (directories
[i
]);
611 free ((char *) directories
);
616 /* If there is only a directory name, return it. */
617 if (*filename
== '\0')
619 result
= (char **) realloc ((char *) result
, 2 * sizeof (char *));
622 result
[0] = (char *) malloc (directory_len
+ 1);
623 if (result
[0] == NULL
)
625 bcopy (directory_name
, result
[0], directory_len
+ 1);
633 /* There are no unquoted globbing characters in DIRECTORY_NAME.
634 Dequote it before we try to open the directory since there may
635 be quoted globbing characters which should be treated verbatim. */
636 if (directory_len
> 0)
637 dequote_pathname (directory_name
);
639 /* We allocated a small array called RESULT, which we won't be using.
640 Free that memory now. */
643 /* Just return what glob_vector () returns appended to the
646 glob_vector (filename
, (directory_len
== 0 ? "." : directory_name
));
648 if (temp_results
== NULL
|| temp_results
== (char **)&glob_error_return
)
649 return (temp_results
);
651 return (glob_dir_to_array (directory_name
, temp_results
));
654 /* We get to memory_error if the program has run out of memory, or
655 if this is the shell, and we have been interrupted. */
659 register unsigned int i
;
660 for (i
= 0; result
[i
] != NULL
; ++i
)
662 free ((char *) result
);
666 throw_to_top_level ();
679 for (i
= 1; i
< argc
; ++i
)
681 char **value
= glob_filename (argv
[i
]);
683 puts ("Out of memory.");
684 else if (value
== &glob_error_return
)
687 for (i
= 0; value
[i
] != NULL
; i
++)