]>
git.ipfire.org Git - thirdparty/bash.git/blob - lib/glob/glob.c
6a9679fc8365c57027d57eea4e89776752e10ef2
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 1, 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., 675 Mass Ave, Cambridge, MA 02139, 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)
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)
79 # define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
80 #endif /* !HAVE_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
)
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
;
257 register char **name_vector
;
258 register unsigned int i
;
259 int flags
; /* Flags passed to fnmatch (). */
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);
304 strcpy (nextname
, dir
);
305 nextname
[dirlen
++] = '/';
306 strcpy (nextname
+ dirlen
, pat
);
308 if (GLOB_TESTNAME (nextname
) >= 0)
311 nextlink
= (struct globval
*)alloca (sizeof (struct globval
));
312 nextlink
->next
= (struct globval
*)0;
313 nextname
= (char *) malloc (strlen (pat
) + 1);
319 nextlink
->name
= nextname
;
320 strcpy (nextname
, pat
);
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 fnmatch(). 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 dot must be explicity matched, check to see if they do. */
383 if (noglob_dot_filenames
&& dp
->d_name
[0] == '.' && pat
[0] != '.' &&
384 (pat
[0] != '\\' || pat
[1] != '.'))
387 if (fnmatch (pat
, dp
->d_name
, flags
) != FNM_NOMATCH
)
389 nextlink
= (struct globval
*) alloca (sizeof (struct globval
));
390 nextlink
->next
= lastlink
;
391 nextname
= (char *) malloc (D_NAMLEN (dp
) + 1);
392 if (nextname
== NULL
)
398 nextlink
->name
= nextname
;
399 bcopy (dp
->d_name
, nextname
, D_NAMLEN (dp
) + 1);
409 name_vector
= (char **) malloc ((count
+ 1) * sizeof (char *));
410 lose
|= name_vector
== NULL
;
413 /* Have we run out of memory? */
416 /* Here free the strings we have got. */
419 free (lastlink
->name
);
420 lastlink
= lastlink
->next
;
424 throw_to_top_level ();
427 return ((char **)NULL
);
430 /* Copy the name pointers from the linked list into the vector. */
431 for (i
= 0; i
< count
; ++i
)
433 name_vector
[i
] = lastlink
->name
;
434 lastlink
= lastlink
->next
;
437 name_vector
[count
] = NULL
;
438 return (name_vector
);
441 /* Return a new array which is the concatenation of each string in ARRAY
442 to DIR. This function expects you to pass in an allocated ARRAY, and
443 it takes care of free()ing that array. Thus, you might think of this
444 function as side-effecting ARRAY. */
446 glob_dir_to_array (dir
, array
)
449 register unsigned int i
, l
;
457 add_slash
= dir
[l
- 1] != '/';
460 while (array
[i
] != NULL
)
463 result
= (char **) malloc ((i
+ 1) * sizeof (char *));
467 for (i
= 0; array
[i
] != NULL
; i
++)
469 result
[i
] = (char *) malloc (l
+ (add_slash
? 1 : 0)
470 + strlen (array
[i
]) + 1);
471 if (result
[i
] == NULL
)
474 strcpy (result
[i
], dir
);
477 strcpy (result
[i
] + l
+ add_slash
, array
[i
]);
479 (void)sprintf (result
[i
], "%s%s%s", dir
, add_slash
? "/" : "", array
[i
]);
484 /* Free the input array. */
485 for (i
= 0; array
[i
] != NULL
; i
++)
487 free ((char *) array
);
492 /* Do globbing on PATHNAME. Return an array of pathnames that match,
493 marking the end of the array with a null-pointer as an element.
494 If no pathnames match, then the array is empty (first element is null).
495 If there isn't enough memory, then return NULL.
496 If a file system error occurs, return -1; `errno' has the error code. */
498 glob_filename (pathname
)
502 unsigned int result_size
;
503 char *directory_name
, *filename
;
504 unsigned int directory_len
;
506 result
= (char **) malloc (sizeof (char *));
513 /* Find the filename. */
514 filename
= strrchr (pathname
, '/');
515 if (filename
== NULL
)
523 directory_len
= (filename
- pathname
) + 1;
524 directory_name
= (char *) alloca (directory_len
+ 1);
526 bcopy (pathname
, directory_name
, directory_len
);
527 directory_name
[directory_len
] = '\0';
531 /* If directory_name contains globbing characters, then we
532 have to expand the previous levels. Just recurse. */
533 if (glob_pattern_p (directory_name
))
536 register unsigned int i
;
538 if (directory_name
[directory_len
- 1] == '/')
539 directory_name
[directory_len
- 1] = '\0';
541 directories
= glob_filename (directory_name
);
543 if (directories
== NULL
)
545 else if (directories
== (char **)&glob_error_return
)
547 free ((char *) result
);
548 return ((char **) &glob_error_return
);
550 else if (*directories
== NULL
)
552 free ((char *) directories
);
553 free ((char *) result
);
554 return ((char **) &glob_error_return
);
557 /* We have successfully globbed the preceding directory name.
558 For each name in DIRECTORIES, call glob_vector on it and
559 FILENAME. Concatenate the results together. */
560 for (i
= 0; directories
[i
] != NULL
; ++i
)
564 /* Scan directory even on a NULL pathname. That way, `*h/'
565 returns only directories ending in `h', instead of all
566 files ending in `h' with a `/' appended. */
567 temp_results
= glob_vector (filename
, directories
[i
]);
569 /* Handle error cases. */
570 if (temp_results
== NULL
)
572 else if (temp_results
== (char **)&glob_error_return
)
573 /* This filename is probably not a directory. Ignore it. */
578 register unsigned int l
;
580 array
= glob_dir_to_array (directories
[i
], temp_results
);
582 while (array
[l
] != NULL
)
586 (char **)realloc (result
, (result_size
+ l
) * sizeof (char *));
591 for (l
= 0; array
[l
] != NULL
; ++l
)
592 result
[result_size
++ - 1] = array
[l
];
594 result
[result_size
- 1] = NULL
;
596 /* Note that the elements of ARRAY are not freed. */
597 free ((char *) array
);
600 /* Free the directories. */
601 for (i
= 0; directories
[i
]; i
++)
602 free (directories
[i
]);
604 free ((char *) directories
);
609 /* If there is only a directory name, return it. */
610 if (*filename
== '\0')
612 result
= (char **) realloc ((char *) result
, 2 * sizeof (char *));
615 result
[0] = (char *) malloc (directory_len
+ 1);
616 if (result
[0] == NULL
)
618 bcopy (directory_name
, result
[0], directory_len
+ 1);
626 /* There are no unquoted globbing characters in DIRECTORY_NAME.
627 Dequote it before we try to open the directory since there may
628 be quoted globbing characters which should be treated verbatim. */
629 if (directory_len
> 0)
630 dequote_pathname (directory_name
);
632 /* We allocated a small array called RESULT, which we won't be using.
633 Free that memory now. */
636 /* Just return what glob_vector () returns appended to the
639 glob_vector (filename
, (directory_len
== 0 ? "." : directory_name
));
641 if (temp_results
== NULL
|| temp_results
== (char **)&glob_error_return
)
642 return (temp_results
);
644 return (glob_dir_to_array (directory_name
, temp_results
));
647 /* We get to memory_error if the program has run out of memory, or
648 if this is the shell, and we have been interrupted. */
652 register unsigned int i
;
653 for (i
= 0; result
[i
] != NULL
; ++i
)
655 free ((char *) result
);
659 throw_to_top_level ();
672 for (i
= 1; i
< argc
; ++i
)
674 char **value
= glob_filename (argv
[i
]);
676 puts ("Out of memory.");
677 else if (value
== &glob_error_return
)
680 for (i
= 0; value
[i
] != NULL
; i
++)