| File: | rpmio/rpmglob.c | 
| Warning: | line 717, column 6 Value stored to 'meta' is never read | 
| 1 | #include "system.h" | 
| 2 | |
| 3 | /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc. | 
| 4 | |
| 5 | This library is free software; you can redistribute it and/or | 
| 6 | modify it under the terms of the GNU Library General Public License as | 
| 7 | published by the Free Software Foundation; either version 2 of the | 
| 8 | License, or (at your option) any later version. | 
| 9 | |
| 10 | This library is distributed in the hope that it will be useful, | 
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 
| 13 | Library General Public License for more details. | 
| 14 | |
| 15 | You should have received a copy of the GNU Library General Public | 
| 16 | License along with this library; see the file COPYING.LIB. If not, | 
| 17 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 
| 18 | Boston, MA 02111-1307, USA. */ | 
| 19 | |
| 20 | /* AIX requires this to be the first thing in the file. */ | 
| 21 | #if defined _AIX && !defined __GNUC__4 | 
| 22 | #pragma alloca | 
| 23 | #endif | 
| 24 | |
| 25 | #include "system.h" | 
| 26 | |
| 27 | #include <stdlib.h> | 
| 28 | #include <string.h> | 
| 29 | #include <pwd.h> | 
| 30 | #include <assert.h> | 
| 31 | #include <sys/stat.h> /* S_ISDIR */ | 
| 32 | |
| 33 | /* Bits set in the FLAGS argument to `glob'. */ | 
| 34 | #define GLOB_ERR(1 << 0) (1 << 0) /* Return on read errors. */ | 
| 35 | #define GLOB_MARK(1 << 1) (1 << 1) /* Append a slash to each name. */ | 
| 36 | #define GLOB_NOSORT(1 << 2) (1 << 2) /* Don't sort the names. */ | 
| 37 | #define GLOB_DOOFFS(1 << 3) (1 << 3) /* Insert PGLOB->gl_offs NULLs. */ | 
| 38 | #define GLOB_NOCHECK(1 << 4) (1 << 4) /* If nothing matches, return the pattern. */ | 
| 39 | #define GLOB_APPEND(1 << 5) (1 << 5) /* Append to results of a previous call. */ | 
| 40 | #define GLOB_NOESCAPE(1 << 6) (1 << 6) /* Backslashes don't quote metacharacters. */ | 
| 41 | #define GLOB_PERIOD(1 << 7) (1 << 7) /* Leading `.' can be matched by metachars. */ | 
| 42 | |
| 43 | #define GLOB_MAGCHAR(1 << 8) (1 << 8) /* Set in gl_flags if any metachars seen. */ | 
| 44 | #define GLOB_ALTDIRFUNC(1 << 9) (1 << 9) /* Use gl_opendir et al functions. */ | 
| 45 | #define GLOB_BRACE(1 << 10) (1 << 10) /* Expand "{a,b}" to "a" "b". */ | 
| 46 | #define GLOB_NOMAGIC(1 << 11) (1 << 11) /* If no magic chars, return the pattern. */ | 
| 47 | #define GLOB_TILDE(1 << 12) (1 << 12) /* Expand ~user and ~ to home directories. */ | 
| 48 | #define GLOB_ONLYDIR(1 << 13) (1 << 13) /* Match only directories. */ | 
| 49 | #define GLOB_TILDE_CHECK(1 << 14) (1 << 14) /* Like GLOB_TILDE but return an error | 
| 50 | if the user name is not available. */ | 
| 51 | #define __GLOB_FLAGS((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)| (1 << 6)|(1 << 4)|(1 << 5)| (1 << 7) |(1 << 9)|(1 << 10)| (1 << 11)|(1 << 12 )|(1 << 13)|(1 << 14)) (GLOB_ERR(1 << 0)|GLOB_MARK(1 << 1)|GLOB_NOSORT(1 << 2)|GLOB_DOOFFS(1 << 3)| \ | 
| 52 | GLOB_NOESCAPE(1 << 6)|GLOB_NOCHECK(1 << 4)|GLOB_APPEND(1 << 5)| \ | 
| 53 | GLOB_PERIOD(1 << 7)|GLOB_ALTDIRFUNC(1 << 9)|GLOB_BRACE(1 << 10)| \ | 
| 54 | GLOB_NOMAGIC(1 << 11)|GLOB_TILDE(1 << 12)|GLOB_ONLYDIR(1 << 13)|GLOB_TILDE_CHECK(1 << 14)) | 
| 55 | |
| 56 | /* Error returns from `glob'. */ | 
| 57 | #define GLOB_NOSPACE1 1 /* Ran out of memory. */ | 
| 58 | #define GLOB_ABORTED2 2 /* Read error. */ | 
| 59 | #define GLOB_NOMATCH3 3 /* No matches found. */ | 
| 60 | #define GLOB_NOSYS4 4 /* Not implemented. */ | 
| 61 | |
| 62 | /* Structure describing a globbing run. */ | 
| 63 | typedef struct { | 
| 64 | size_t gl_pathc; /* Count of paths matched by the pattern. */ | 
| 65 | char **gl_pathv; /* List of matched pathnames. */ | 
| 66 | size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ | 
| 67 | int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ | 
| 68 | |
| 69 | /* If the GLOB_ALTDIRFUNC flag is set, the following functions | 
| 70 | are used instead of the normal file access functions. */ | 
| 71 | void (*gl_closedir)(void *); | 
| 72 | struct dirent *(*gl_readdir)(void *); | 
| 73 | void *(*gl_opendir)(const char *); | 
| 74 | int (*gl_lstat)(const char *, struct stat *); | 
| 75 | int (*gl_stat)(const char *, struct stat *); | 
| 76 | } glob_t; | 
| 77 | |
| 78 | #define NAMLEN(_d)(strlen((_d)->d_name)) NLENGTH(_d)(strlen((_d)->d_name)) | 
| 79 | |
| 80 | #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__6 | 
| 81 | /* Posix does not require that the d_ino field be present, and some | 
| 82 | systems do not provide it. */ | 
| 83 | #define REAL_DIR_ENTRY(dp)(dp->d_ino != 0) 1 | 
| 84 | #else | 
| 85 | #define REAL_DIR_ENTRY(dp)(dp->d_ino != 0) (dp->d_ino != 0) | 
| 86 | #endif /* POSIX */ | 
| 87 | |
| 88 | #include <errno(*__errno_location ()).h> | 
| 89 | #ifndef __set_errno | 
| 90 | #define __set_errno(val)(*__errno_location ()) = (val) errno(*__errno_location ()) = (val) | 
| 91 | #endif | 
| 92 | |
| 93 | #include <popt.h> | 
| 94 | #include <rpm/rpmfileutil.h> | 
| 95 | #include <rpm/rpmurl.h> | 
| 96 | |
| 97 | #include "debug.h" | 
| 98 | |
| 99 | /* Outcomment the following line for production quality code. */ | 
| 100 | /* #define NDEBUG 1 */ | 
| 101 | |
| 102 | #define GLOB_INTERFACE_VERSION1 1 | 
| 103 | |
| 104 | static void globfree(glob_t * pglob); | 
| 105 | static inline const char *next_brace_sub(const char *begin); | 
| 106 | static int glob_in_dir(const char *pattern, const char *directory, | 
| 107 | int flags, | 
| 108 | int (*errfunc) (const char *, int), | 
| 109 | glob_t * pglob); | 
| 110 | static int prefix_array(const char *prefix, char **array, size_t n); | 
| 111 | static int collated_compare(const void *, const void *); | 
| 112 | |
| 113 | #ifndef HAVE_MEMPCPY1 | 
| 114 | static void * mempcpy(void *dest, const void *src, size_t n) | 
| 115 | { | 
| 116 | return (char *) memcpy(dest, src, n) + n; | 
| 117 | } | 
| 118 | #endif | 
| 119 | |
| 120 | /* Find the end of the sub-pattern in a brace expression. We define | 
| 121 | this as an inline function if the compiler permits. */ | 
| 122 | static inline const char *next_brace_sub(const char *begin) | 
| 123 | { | 
| 124 | unsigned int depth = 0; | 
| 125 | const char *cp = begin; | 
| 126 | |
| 127 | while (*cp != '\0') { | 
| 128 | if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0)) | 
| 129 | break; | 
| 130 | |
| 131 | if (*cp++ == '{') | 
| 132 | depth++; | 
| 133 | } | 
| 134 | |
| 135 | return *cp != '\0' ? cp : NULL((void*)0); | 
| 136 | } | 
| 137 | |
| 138 | static int __glob_pattern_p(const char *pattern, int quote); | 
| 139 | |
| 140 | /* Do glob searching for PATTERN, placing results in PGLOB. | 
| 141 | The bits defined above may be set in FLAGS. | 
| 142 | If a directory cannot be opened or read and ERRFUNC is not nil, | 
| 143 | it is called with the pathname that caused the error, and the | 
| 144 | `errno' value from the failing call; if it returns non-zero | 
| 145 | `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored. | 
| 146 | If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. | 
| 147 | Otherwise, `glob' returns zero. */ | 
| 148 | static int | 
| 149 | glob(const char *pattern, int flags, | 
| 150 | int (*errfunc)(const char *, int), glob_t * pglob) | 
| 151 | { | 
| 152 | const char *filename; | 
| 153 | const char *dirname; | 
| 154 | size_t dirlen; | 
| 155 | int status; | 
| 156 | int oldcount; | 
| 157 | |
| 158 | if (pattern == NULL((void*)0) || pglob == NULL((void*)0) || (flags & ~__GLOB_FLAGS((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)| (1 << 6)|(1 << 4)|(1 << 5)| (1 << 7) |(1 << 9)|(1 << 10)| (1 << 11)|(1 << 12 )|(1 << 13)|(1 << 14))) != 0) { | 
| 159 | __set_errno(EINVAL)(*__errno_location ()) = (22); | 
| 160 | return -1; | 
| 161 | } | 
| 162 | |
| 163 | if (flags & GLOB_BRACE(1 << 10)) { | 
| 164 | const char *begin = strchr(pattern, '{'); | 
| 165 | if (begin != NULL((void*)0)) { | 
| 166 | /* Allocate working buffer large enough for our work. Note that | 
| 167 | we have at least an opening and closing brace. */ | 
| 168 | int firstc; | 
| 169 | char *alt_start; | 
| 170 | const char *p; | 
| 171 | const char *next; | 
| 172 | const char *rest; | 
| 173 | size_t rest_len; | 
| 174 | char onealt[strlen(pattern) - 1]; | 
| 175 | |
| 176 | /* We know the prefix for all sub-patterns. */ | 
| 177 | alt_start = mempcpy(onealt, pattern, begin - pattern); | 
| 178 | |
| 179 | /* Find the first sub-pattern and at the same time find the | 
| 180 | rest after the closing brace. */ | 
| 181 | next = next_brace_sub(begin + 1); | 
| 182 | if (next == NULL((void*)0)) { | 
| 183 | /* It is an illegal expression. */ | 
| 184 | return glob(pattern, flags & ~GLOB_BRACE(1 << 10), errfunc, pglob); | 
| 185 | } | 
| 186 | |
| 187 | /* Now find the end of the whole brace expression. */ | 
| 188 | rest = next; | 
| 189 | while (*rest != '}') { | 
| 190 | rest = next_brace_sub(rest + 1); | 
| 191 | if (rest == NULL((void*)0)) { | 
| 192 | /* It is an illegal expression. */ | 
| 193 | return glob(pattern, flags & ~GLOB_BRACE(1 << 10), errfunc, | 
| 194 | pglob); | 
| 195 | } | 
| 196 | } | 
| 197 | /* Please note that we now can be sure the brace expression | 
| 198 | is well-formed. */ | 
| 199 | rest_len = strlen(++rest) + 1; | 
| 200 | |
| 201 | /* We have a brace expression. BEGIN points to the opening {, | 
| 202 | NEXT points past the terminator of the first element, and END | 
| 203 | points past the final }. We will accumulate result names from | 
| 204 | recursive runs for each brace alternative in the buffer using | 
| 205 | GLOB_APPEND. */ | 
| 206 | |
| 207 | if (!(flags & GLOB_APPEND(1 << 5))) { | 
| 208 | /* This call is to set a new vector, so clear out the | 
| 209 | vector so we can append to it. */ | 
| 210 | pglob->gl_pathc = 0; | 
| 211 | pglob->gl_pathv = NULL((void*)0); | 
| 212 | } | 
| 213 | firstc = pglob->gl_pathc; | 
| 214 | |
| 215 | p = begin + 1; | 
| 216 | while (1) { | 
| 217 | int result; | 
| 218 | |
| 219 | /* Construct the new glob expression. */ | 
| 220 | mempcpy(mempcpy(alt_start, p, next - p), rest, rest_len); | 
| 221 | |
| 222 | result = glob(onealt, | 
| 223 | ((flags & ~(GLOB_NOCHECK(1 << 4) | GLOB_NOMAGIC(1 << 11))) | 
| 224 | | GLOB_APPEND(1 << 5)), errfunc, pglob); | 
| 225 | |
| 226 | /* If we got an error, return it. */ | 
| 227 | if (result && result != GLOB_NOMATCH3) { | 
| 228 | if (!(flags & GLOB_APPEND(1 << 5))) | 
| 229 | globfree(pglob); | 
| 230 | return result; | 
| 231 | } | 
| 232 | |
| 233 | if (*next == '}') | 
| 234 | /* We saw the last entry. */ | 
| 235 | break; | 
| 236 | |
| 237 | p = next + 1; | 
| 238 | next = next_brace_sub(p); | 
| 239 | assert(next != NULL)((void) sizeof ((next != ((void*)0)) == 0), __extension__ ({ if (next != ((void*)0)) ; else __assert_fail ("next != NULL", "rpmglob.c" , 239, __extension__ __PRETTY_FUNCTION__); })); | 
| 240 | } | 
| 241 | |
| 242 | if (pglob->gl_pathc != firstc) | 
| 243 | /* We found some entries. */ | 
| 244 | return 0; | 
| 245 | else if (!(flags & (GLOB_NOCHECK(1 << 4) | GLOB_NOMAGIC(1 << 11)))) | 
| 246 | return GLOB_NOMATCH3; | 
| 247 | } | 
| 248 | } | 
| 249 | |
| 250 | /* Find the filename. */ | 
| 251 | filename = strrchr(pattern, '/'); | 
| 252 | if (filename == NULL((void*)0)) { | 
| 253 | /* This can mean two things: a simple name or "~name". The latter | 
| 254 | case is nothing but a notation for a directory. */ | 
| 255 | if ((flags & (GLOB_TILDE(1 << 12) | GLOB_TILDE_CHECK(1 << 14))) && pattern[0] == '~') { | 
| 256 | dirname = pattern; | 
| 257 | dirlen = strlen(pattern); | 
| 258 | |
| 259 | /* Set FILENAME to NULL as a special flag. This is ugly but | 
| 260 | other solutions would require much more code. We test for | 
| 261 | this special case below. */ | 
| 262 | filename = NULL((void*)0); | 
| 263 | } else { | 
| 264 | filename = pattern; | 
| 265 | dirname = "."; | 
| 266 | dirlen = 0; | 
| 267 | } | 
| 268 | } else if (filename == pattern) { | 
| 269 | /* "/pattern". */ | 
| 270 | dirname = "/"; | 
| 271 | dirlen = 1; | 
| 272 | ++filename; | 
| 273 | } else { | 
| 274 | char *newp; | 
| 275 | dirlen = filename - pattern; | 
| 276 | newp = (char *) alloca(dirlen + 1)__builtin_alloca (dirlen + 1); | 
| 277 | *((char *) mempcpy(newp, pattern, dirlen)) = '\0'; | 
| 278 | dirname = newp; | 
| 279 | ++filename; | 
| 280 | |
| 281 | if (filename[0] == '\0' && dirlen > 1) { | 
| 282 | /* "pattern/". Expand "pattern", appending slashes. */ | 
| 283 | int val = glob(dirname, flags | GLOB_MARK(1 << 1), errfunc, pglob); | 
| 284 | if (val == 0) | 
| 285 | pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK(1 << 1)) | 
| 286 | | (flags & GLOB_MARK(1 << 1))); | 
| 287 | return val; | 
| 288 | } | 
| 289 | } | 
| 290 | |
| 291 | if (!(flags & GLOB_APPEND(1 << 5))) { | 
| 292 | pglob->gl_pathc = 0; | 
| 293 | pglob->gl_pathv = NULL((void*)0); | 
| 294 | } | 
| 295 | |
| 296 | oldcount = pglob->gl_pathc; | 
| 297 | |
| 298 | if ((flags & (GLOB_TILDE(1 << 12) | GLOB_TILDE_CHECK(1 << 14))) && dirname[0] == '~') { | 
| 299 | if (dirname[1] == '\0' || dirname[1] == '/') { | 
| 300 | /* Look up home directory. */ | 
| 301 | const char *home_dir = getenv("HOME")secure_getenv("HOME"); | 
| 302 | if (home_dir == NULL((void*)0) || home_dir[0] == '\0') { | 
| 303 | int success; | 
| 304 | char *name; | 
| 305 | success = (name = getlogin()) != NULL((void*)0); | 
| 306 | if (success) { | 
| 307 | struct passwd *p; | 
| 308 | p = getpwnam(name); | 
| 309 | if (p != NULL((void*)0)) | 
| 310 | home_dir = p->pw_dir; | 
| 311 | } | 
| 312 | } | 
| 313 | if (home_dir == NULL((void*)0) || home_dir[0] == '\0') { | 
| 314 | if (flags & GLOB_TILDE_CHECK(1 << 14)) | 
| 315 | return GLOB_NOMATCH3; | 
| 316 | else | 
| 317 | home_dir = "~"; /* No luck. */ | 
| 318 | } | 
| 319 | /* Now construct the full directory. */ | 
| 320 | if (dirname[1] == '\0') | 
| 321 | dirname = home_dir; | 
| 322 | else { | 
| 323 | char *newp; | 
| 324 | size_t home_len = strlen(home_dir); | 
| 325 | newp = (char *) alloca(home_len + dirlen)__builtin_alloca (home_len + dirlen); | 
| 326 | mempcpy(mempcpy(newp, home_dir, home_len), | 
| 327 | &dirname[1], dirlen); | 
| 328 | dirname = newp; | 
| 329 | } | 
| 330 | } | 
| 331 | else { | 
| 332 | char *end_name = strchr(dirname, '/'); | 
| 333 | const char *user_name; | 
| 334 | const char *home_dir; | 
| 335 | |
| 336 | if (end_name == NULL((void*)0)) | 
| 337 | user_name = dirname + 1; | 
| 338 | else { | 
| 339 | char *newp; | 
| 340 | newp = (char *) alloca(end_name - dirname + 1)__builtin_alloca (end_name - dirname + 1); | 
| 341 | *((char *) mempcpy(newp, dirname + 1, end_name - dirname)) | 
| 342 | = '\0'; | 
| 343 | user_name = newp; | 
| 344 | } | 
| 345 | |
| 346 | /* Look up specific user's home directory. */ | 
| 347 | { | 
| 348 | struct passwd *p; | 
| 349 | p = getpwnam(user_name); | 
| 350 | if (p != NULL((void*)0)) | 
| 351 | home_dir = p->pw_dir; | 
| 352 | else | 
| 353 | home_dir = NULL((void*)0); | 
| 354 | } | 
| 355 | /* If we found a home directory use this. */ | 
| 356 | if (home_dir != NULL((void*)0)) { | 
| 357 | char *newp; | 
| 358 | size_t home_len = strlen(home_dir); | 
| 359 | size_t rest_len = end_name == NULL((void*)0) ? 0 : strlen(end_name); | 
| 360 | newp = (char *) alloca(home_len + rest_len + 1)__builtin_alloca (home_len + rest_len + 1); | 
| 361 | *((char *) mempcpy(mempcpy(newp, home_dir, home_len), | 
| 362 | end_name, rest_len)) = '\0'; | 
| 363 | dirname = newp; | 
| 364 | } else if (flags & GLOB_TILDE_CHECK(1 << 14)) | 
| 365 | /* We have to regard it as an error if we cannot find the | 
| 366 | home directory. */ | 
| 367 | return GLOB_NOMATCH3; | 
| 368 | } | 
| 369 | } | 
| 370 | |
| 371 | /* Now test whether we looked for "~" or "~NAME". In this case we | 
| 372 | can give the answer now. */ | 
| 373 | if (filename == NULL((void*)0)) { | 
| 374 | struct stat st; | 
| 375 | |
| 376 | /* Return the directory if we don't check for error or if it exists. */ | 
| 377 | if ((flags & GLOB_NOCHECK(1 << 4)) | 
| 378 | || (((flags & GLOB_ALTDIRFUNC(1 << 9)) | 
| 379 | ? (*pglob->gl_stat) (dirname, &st) | 
| 380 | : stat(dirname, &st)) == 0 && S_ISDIR(st.st_mode)((((st.st_mode)) & 0170000) == (0040000)))) { | 
| 381 | pglob->gl_pathv | 
| 382 | = (char **) xrealloc(pglob->gl_pathv,rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + 1 + 1) * sizeof (char *))) | 
| 383 | (pglob->gl_pathc +rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + 1 + 1) * sizeof (char *))) | 
| 384 | ((flags & GLOB_DOOFFS) ?rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + 1 + 1) * sizeof (char *))) | 
| 385 | pglob->gl_offs : 0) +rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + 1 + 1) * sizeof (char *))) | 
| 386 | 1 + 1) * sizeof(char *))rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + 1 + 1) * sizeof (char *))); | 
| 387 | |
| 388 | if (flags & GLOB_DOOFFS(1 << 3)) | 
| 389 | while (pglob->gl_pathc < pglob->gl_offs) | 
| 390 | pglob->gl_pathv[pglob->gl_pathc++] = NULL((void*)0); | 
| 391 | |
| 392 | pglob->gl_pathv[pglob->gl_pathc] = xstrdup(dirname)rstrdup((dirname)); | 
| 393 | if (pglob->gl_pathv[pglob->gl_pathc] == NULL((void*)0)) { | 
| 394 | free(pglob->gl_pathv); | 
| 395 | return GLOB_NOSPACE1; | 
| 396 | } | 
| 397 | pglob->gl_pathv[++pglob->gl_pathc] = NULL((void*)0); | 
| 398 | pglob->gl_flags = flags; | 
| 399 | |
| 400 | return 0; | 
| 401 | } | 
| 402 | |
| 403 | /* Not found. */ | 
| 404 | return GLOB_NOMATCH3; | 
| 405 | } | 
| 406 | |
| 407 | if (__glob_pattern_p(dirname, !(flags & GLOB_NOESCAPE(1 << 6)))) { | 
| 408 | /* The directory name contains metacharacters, so we | 
| 409 | have to glob for the directory, and then glob for | 
| 410 | the pattern in each directory found. */ | 
| 411 | glob_t dirs; | 
| 412 | register int i; | 
| 413 | |
| 414 | if ((flags & GLOB_ALTDIRFUNC(1 << 9)) != 0) { | 
| 415 | /* Use the alternative access functions also in the recursive | 
| 416 | call. */ | 
| 417 | dirs.gl_opendir = pglob->gl_opendir; | 
| 418 | dirs.gl_readdir = pglob->gl_readdir; | 
| 419 | dirs.gl_closedir = pglob->gl_closedir; | 
| 420 | dirs.gl_stat = pglob->gl_stat; | 
| 421 | dirs.gl_lstat = pglob->gl_lstat; | 
| 422 | } | 
| 423 | |
| 424 | status = glob(dirname, | 
| 425 | ((flags & (GLOB_ERR(1 << 0) | GLOB_NOCHECK(1 << 4) | GLOB_NOESCAPE(1 << 6) | 
| 426 | | GLOB_ALTDIRFUNC(1 << 9))) | 
| 427 | | GLOB_NOSORT(1 << 2) | GLOB_ONLYDIR(1 << 13)), errfunc, &dirs); | 
| 428 | if (status != 0) | 
| 429 | return status; | 
| 430 | |
| 431 | /* We have successfully globbed the preceding directory name. | 
| 432 | For each name we found, call glob_in_dir on it and FILENAME, | 
| 433 | appending the results to PGLOB. */ | 
| 434 | for (i = 0; i < dirs.gl_pathc; ++i) { | 
| 435 | int old_pathc = pglob->gl_pathc; | 
| 436 | status = glob_in_dir(filename, dirs.gl_pathv[i], | 
| 437 | ((flags | GLOB_APPEND(1 << 5)) | 
| 438 | & ~(GLOB_NOCHECK(1 << 4) | GLOB_ERR(1 << 0))), | 
| 439 | errfunc, pglob); | 
| 440 | if (status == GLOB_NOMATCH3) | 
| 441 | /* No matches in this directory. Try the next. */ | 
| 442 | continue; | 
| 443 | |
| 444 | if (status != 0) { | 
| 445 | globfree(&dirs); | 
| 446 | globfree(pglob); | 
| 447 | return status; | 
| 448 | } | 
| 449 | |
| 450 | /* Stick the directory on the front of each name. */ | 
| 451 | if (prefix_array(dirs.gl_pathv[i], | 
| 452 | &pglob->gl_pathv[old_pathc], | 
| 453 | pglob->gl_pathc - old_pathc)) { | 
| 454 | globfree(&dirs); | 
| 455 | globfree(pglob); | 
| 456 | return GLOB_NOSPACE1; | 
| 457 | } | 
| 458 | } | 
| 459 | |
| 460 | flags |= GLOB_MAGCHAR(1 << 8); | 
| 461 | |
| 462 | /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. | 
| 463 | But if we have not found any matching entry and thie GLOB_NOCHECK | 
| 464 | flag was set we must return the list consisting of the disrectory | 
| 465 | names followed by the filename. */ | 
| 466 | if (pglob->gl_pathc == oldcount) { | 
| 467 | /* No matches. */ | 
| 468 | if (flags & GLOB_NOCHECK(1 << 4)) { | 
| 469 | size_t filename_len = strlen(filename) + 1; | 
| 470 | char **new_pathv; | 
| 471 | struct stat st; | 
| 472 | |
| 473 | /* This is an pessimistic guess about the size. */ | 
| 474 | pglob->gl_pathv | 
| 475 | = (char **) xrealloc(pglob->gl_pathv,rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + dirs.gl_pathc + 1) * sizeof(char *))) | 
| 476 | (pglob->gl_pathc +rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + dirs.gl_pathc + 1) * sizeof(char *))) | 
| 477 | ((flags & GLOB_DOOFFS) ?rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + dirs.gl_pathc + 1) * sizeof(char *))) | 
| 478 | pglob->gl_offs : 0) +rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + dirs.gl_pathc + 1) * sizeof(char *))) | 
| 479 | dirs.gl_pathc + 1) *rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + dirs.gl_pathc + 1) * sizeof(char *))) | 
| 480 | sizeof(char *))rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob->gl_offs : 0) + dirs.gl_pathc + 1) * sizeof(char *))); | 
| 481 | |
| 482 | if (flags & GLOB_DOOFFS(1 << 3)) | 
| 483 | while (pglob->gl_pathc < pglob->gl_offs) | 
| 484 | pglob->gl_pathv[pglob->gl_pathc++] = NULL((void*)0); | 
| 485 | |
| 486 | for (i = 0; i < dirs.gl_pathc; ++i) { | 
| 487 | const char *dir = dirs.gl_pathv[i]; | 
| 488 | size_t dir_len = strlen(dir); | 
| 489 | |
| 490 | /* First check whether this really is a directory. */ | 
| 491 | if (((flags & GLOB_ALTDIRFUNC(1 << 9)) | 
| 492 | ? (*pglob->gl_stat) (dir, &st) : stat(dir, | 
| 493 | &st)) != 0 | 
| 494 | || !S_ISDIR(st.st_mode)((((st.st_mode)) & 0170000) == (0040000))) | 
| 495 | /* No directory, ignore this entry. */ | 
| 496 | continue; | 
| 497 | |
| 498 | pglob->gl_pathv[pglob->gl_pathc] = xmalloc(dir_len + 1rmalloc((dir_len + 1 + filename_len)) | 
| 499 | +rmalloc((dir_len + 1 + filename_len)) | 
| 500 | filename_len)rmalloc((dir_len + 1 + filename_len)); | 
| 501 | mempcpy(mempcpy | 
| 502 | (mempcpy | 
| 503 | (pglob->gl_pathv[pglob->gl_pathc], dir, | 
| 504 | dir_len), "/", 1), filename, filename_len); | 
| 505 | ++pglob->gl_pathc; | 
| 506 | } | 
| 507 | |
| 508 | pglob->gl_pathv[pglob->gl_pathc] = NULL((void*)0); | 
| 509 | pglob->gl_flags = flags; | 
| 510 | |
| 511 | /* Now we know how large the gl_pathv vector must be. */ | 
| 512 | new_pathv = (char **) xrealloc(pglob->gl_pathv,rrealloc((pglob->gl_pathv), (((pglob->gl_pathc + 1) * sizeof (char *)))) | 
| 513 | ((pglob->gl_pathc + 1)rrealloc((pglob->gl_pathv), (((pglob->gl_pathc + 1) * sizeof (char *)))) | 
| 514 | * sizeof(char *)))rrealloc((pglob->gl_pathv), (((pglob->gl_pathc + 1) * sizeof (char *)))); | 
| 515 | pglob->gl_pathv = new_pathv; | 
| 516 | } else | 
| 517 | return GLOB_NOMATCH3; | 
| 518 | } | 
| 519 | |
| 520 | globfree(&dirs); | 
| 521 | } else { | 
| 522 | status = glob_in_dir(filename, dirname, flags, errfunc, pglob); | 
| 523 | if (status != 0) | 
| 524 | return status; | 
| 525 | |
| 526 | if (dirlen > 0) { | 
| 527 | /* Stick the directory on the front of each name. */ | 
| 528 | int ignore = oldcount; | 
| 529 | |
| 530 | if ((flags & GLOB_DOOFFS(1 << 3)) && ignore < pglob->gl_offs) | 
| 531 | ignore = pglob->gl_offs; | 
| 532 | |
| 533 | if (prefix_array(dirname, | 
| 534 | &pglob->gl_pathv[ignore], | 
| 535 | pglob->gl_pathc - ignore)) { | 
| 536 | globfree(pglob); | 
| 537 | return GLOB_NOSPACE1; | 
| 538 | } | 
| 539 | } | 
| 540 | } | 
| 541 | |
| 542 | if (flags & GLOB_MARK(1 << 1)) { | 
| 543 | /* Append slashes to directory names. */ | 
| 544 | int i; | 
| 545 | struct stat st; | 
| 546 | for (i = oldcount; i < pglob->gl_pathc; ++i) | 
| 547 | if (((flags & GLOB_ALTDIRFUNC(1 << 9)) | 
| 548 | ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st) | 
| 549 | : stat(pglob->gl_pathv[i], &st)) == 0 | 
| 550 | && S_ISDIR(st.st_mode)((((st.st_mode)) & 0170000) == (0040000))) { | 
| 551 | size_t len = strlen(pglob->gl_pathv[i]) + 2; | 
| 552 | char *new = xrealloc(pglob->gl_pathv[i], len)rrealloc((pglob->gl_pathv[i]), (len)); | 
| 553 | strcpy(&new[len - 2], "/"); | 
| 554 | pglob->gl_pathv[i] = new; | 
| 555 | } | 
| 556 | } | 
| 557 | |
| 558 | if (!(flags & GLOB_NOSORT(1 << 2))) { | 
| 559 | /* Sort the vector. */ | 
| 560 | int non_sort = oldcount; | 
| 561 | |
| 562 | if ((flags & GLOB_DOOFFS(1 << 3)) && pglob->gl_offs > oldcount) | 
| 563 | non_sort = pglob->gl_offs; | 
| 564 | |
| 565 | qsort(& pglob->gl_pathv[non_sort], | 
| 566 | pglob->gl_pathc - non_sort, | 
| 567 | sizeof(char *), collated_compare); | 
| 568 | } | 
| 569 | |
| 570 | return 0; | 
| 571 | } | 
| 572 | |
| 573 | |
| 574 | /* Free storage allocated in PGLOB by a previous `glob' call. */ | 
| 575 | static void globfree(glob_t * pglob) | 
| 576 | { | 
| 577 | if (pglob->gl_pathv != NULL((void*)0)) { | 
| 578 | register int i; | 
| 579 | for (i = 0; i < pglob->gl_pathc; ++i) | 
| 580 | if (pglob->gl_pathv[i] != NULL((void*)0)) | 
| 581 | free(pglob->gl_pathv[i]); | 
| 582 | free(pglob->gl_pathv); | 
| 583 | } | 
| 584 | } | 
| 585 | |
| 586 | |
| 587 | /* Do a collated comparison of A and B. */ | 
| 588 | static int collated_compare(const void * a, const void * b) | 
| 589 | { | 
| 590 | const char *const s1 = *(const char *const *const) a; | 
| 591 | const char *const s2 = *(const char *const *const) b; | 
| 592 | |
| 593 | if (s1 == s2) | 
| 594 | return 0; | 
| 595 | if (s1 == NULL((void*)0)) | 
| 596 | return 1; | 
| 597 | if (s2 == NULL((void*)0)) | 
| 598 | return -1; | 
| 599 | return strcoll(s1, s2); | 
| 600 | } | 
| 601 | |
| 602 | |
| 603 | /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's | 
| 604 | elements in place. Return nonzero if out of memory, zero if successful. | 
| 605 | A slash is inserted between DIRNAME and each elt of ARRAY, | 
| 606 | unless DIRNAME is just "/". Each old element of ARRAY is freed. */ | 
| 607 | static int prefix_array(const char *dirname, char **array, size_t n) | 
| 608 | { | 
| 609 | register size_t i; | 
| 610 | size_t dirlen = strlen(dirname); | 
| 611 | |
| 612 | if (dirlen == 1 && dirname[0] == '/') | 
| 613 | /* DIRNAME is just "/", so normal prepending would get us "//foo". | 
| 614 | We want "/foo" instead, so don't prepend any chars from DIRNAME. */ | 
| 615 | dirlen = 0; | 
| 616 | |
| 617 | for (i = 0; i < n; ++i) { | 
| 618 | size_t eltlen = strlen(array[i]) + 1; | 
| 619 | char *new = (char *) xmalloc(dirlen + 1 + eltlen)rmalloc((dirlen + 1 + eltlen)); | 
| 620 | { | 
| 621 | char *endp = (char *) mempcpy(new, dirname, dirlen); | 
| 622 | *endp++ = '/'; | 
| 623 | mempcpy(endp, array[i], eltlen); | 
| 624 | } | 
| 625 | free(array[i]); | 
| 626 | array[i] = new; | 
| 627 | } | 
| 628 | |
| 629 | return 0; | 
| 630 | } | 
| 631 | |
| 632 | /* Return nonzero if PATTERN contains any metacharacters. | 
| 633 | Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ | 
| 634 | static int __glob_pattern_p(const char *pattern, int quote) | 
| 635 | { | 
| 636 | register const char *p; | 
| 637 | int openBrackets = 0; | 
| 638 | |
| 639 | for (p = pattern; *p != '\0'; ++p) | 
| 640 | switch (*p) { | 
| 641 | case '?': | 
| 642 | case '*': | 
| 643 | return 1; | 
| 644 | |
| 645 | case '\\': | 
| 646 | if (quote && p[1] != '\0') | 
| 647 | ++p; | 
| 648 | break; | 
| 649 | |
| 650 | case '[': | 
| 651 | openBrackets = 1; | 
| 652 | break; | 
| 653 | |
| 654 | case ']': | 
| 655 | if (openBrackets) | 
| 656 | return 1; | 
| 657 | break; | 
| 658 | } | 
| 659 | |
| 660 | return 0; | 
| 661 | } | 
| 662 | |
| 663 | /* Like `glob', but PATTERN is a final pathname component, | 
| 664 | and matches are searched for in DIRECTORY. | 
| 665 | The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. | 
| 666 | The GLOB_APPEND flag is assumed to be set (always appends). */ | 
| 667 | static int | 
| 668 | glob_in_dir(const char *pattern, const char *directory, int flags, | 
| 669 | int (*errfunc)(const char *, int), glob_t * pglob) | 
| 670 | { | 
| 671 | void * stream = NULL((void*)0); | 
| 672 | |
| 673 | struct globlink { | 
| 674 | struct globlink *next; | 
| 675 | char *name; | 
| 676 | }; | 
| 677 | struct globlink *names = NULL((void*)0); | 
| 678 | size_t nfound; | 
| 679 | int meta; | 
| 680 | int save; | 
| 681 | |
| 682 | meta = __glob_pattern_p(pattern, !(flags & GLOB_NOESCAPE(1 << 6))); | 
| 683 | if (meta == 0) { | 
| 684 | if (flags & (GLOB_NOCHECK(1 << 4) | GLOB_NOMAGIC(1 << 11))) | 
| 685 | /* We need not do any tests. The PATTERN contains no meta | 
| 686 | characters and we must not return an error therefore the | 
| 687 | result will always contain exactly one name. */ | 
| 688 | flags |= GLOB_NOCHECK(1 << 4); | 
| 689 | else { | 
| 690 | /* Since we use the normal file functions we can also use stat() | 
| 691 | to verify the file is there. */ | 
| 692 | struct stat st; | 
| 693 | size_t patlen = strlen(pattern); | 
| 694 | size_t dirlen = strlen(directory); | 
| 695 | char *fullname = (char *) alloca(dirlen + 1 + patlen + 1)__builtin_alloca (dirlen + 1 + patlen + 1); | 
| 696 | |
| 697 | mempcpy(mempcpy(mempcpy(fullname, directory, dirlen), | 
| 698 | "/", 1), pattern, patlen + 1); | 
| 699 | if (((flags & GLOB_ALTDIRFUNC(1 << 9)) | 
| 700 | ? (*pglob->gl_stat) (fullname, &st) | 
| 701 | : stat(fullname, &st)) == 0) | 
| 702 | /* We found this file to be existing. Now tell the rest | 
| 703 | of the function to copy this name into the result. */ | 
| 704 | flags |= GLOB_NOCHECK(1 << 4); | 
| 705 | } | 
| 706 | |
| 707 | nfound = 0; | 
| 708 | } else { | 
| 709 | if (pattern[0] == '\0') { | 
| 710 | /* This is a special case for matching directories like in | 
| 711 | "*a/". */ | 
| 712 | names = (struct globlink *) alloca(sizeof(struct globlink))__builtin_alloca (sizeof(struct globlink)); | 
| 713 | names->name = (char *) xmalloc(1)rmalloc((1)); | 
| 714 | names->name[0] = '\0'; | 
| 715 | names->next = NULL((void*)0); | 
| 716 | nfound = 1; | 
| 717 | meta = 0; | 
| Value stored to 'meta' is never read | |
| 718 | } else { | 
| 719 | stream = ((flags & GLOB_ALTDIRFUNC(1 << 9)) | 
| 720 | ? (*pglob->gl_opendir) (directory) | 
| 721 | : opendir(directory)); | 
| 722 | if (stream == NULL((void*)0)) { | 
| 723 | if (errno(*__errno_location ()) != ENOTDIR20 | 
| 724 | && ((errfunc != NULL((void*)0) && (*errfunc) (directory, errno(*__errno_location ()))) | 
| 725 | || (flags & GLOB_ERR(1 << 0)))) | 
| 726 | return GLOB_ABORTED2; | 
| 727 | nfound = 0; | 
| 728 | meta = 0; | 
| 729 | } else { | 
| 730 | int fnm_flags = ((!(flags & GLOB_PERIOD(1 << 7)) ? FNM_PERIOD(1 << 2) : 0) | | 
| 731 | ((flags & GLOB_NOESCAPE(1 << 6)) ? FNM_NOESCAPE(1 << 1) : 0)); | 
| 732 | nfound = 0; | 
| 733 | flags |= GLOB_MAGCHAR(1 << 8); | 
| 734 | |
| 735 | while (1) { | 
| 736 | const char *name; | 
| 737 | size_t len; | 
| 738 | struct dirent *d = ((flags & GLOB_ALTDIRFUNC(1 << 9)) | 
| 739 | ? (*pglob->gl_readdir) (stream) | 
| 740 | : readdir((DIR *) stream)); | 
| 741 | if (d == NULL((void*)0)) | 
| 742 | break; | 
| 743 | if (!REAL_DIR_ENTRY(d)(d->d_ino != 0)) | 
| 744 | continue; | 
| 745 | |
| 746 | #ifdef HAVE_STRUCT_DIRENT_D_TYPE1 | 
| 747 | /* If we shall match only directories use the information | 
| 748 | provided by the dirent call if possible. */ | 
| 749 | if ((flags & GLOB_ONLYDIR(1 << 13)) | 
| 750 | && d->d_type != DT_UNKNOWNDT_UNKNOWN && d->d_type != DT_DIRDT_DIR) | 
| 751 | continue; | 
| 752 | #endif | 
| 753 | |
| 754 | name = d->d_name; | 
| 755 | |
| 756 | if (fnmatch(pattern, name, fnm_flags) == 0) { | 
| 757 | struct globlink *new = (struct globlink *) | 
| 758 | alloca(sizeof(struct globlink))__builtin_alloca (sizeof(struct globlink)); | 
| 759 | len = NAMLEN(d)(strlen((d)->d_name)); | 
| 760 | new->name = (char *) xmalloc(len + 1)rmalloc((len + 1)); | 
| 761 | *((char *) mempcpy(new->name, name, len)) | 
| 762 | = '\0'; | 
| 763 | new->next = names; | 
| 764 | names = new; | 
| 765 | ++nfound; | 
| 766 | } | 
| 767 | } | 
| 768 | } | 
| 769 | } | 
| 770 | } | 
| 771 | |
| 772 | if (nfound == 0 && (flags & GLOB_NOCHECK(1 << 4))) { | 
| 773 | size_t len = strlen(pattern); | 
| 774 | nfound = 1; | 
| 775 | names = (struct globlink *) alloca(sizeof(struct globlink))__builtin_alloca (sizeof(struct globlink)); | 
| 776 | names->next = NULL((void*)0); | 
| 777 | names->name = (char *) xmalloc(len + 1)rmalloc((len + 1)); | 
| 778 | *((char *) mempcpy(names->name, pattern, len)) = '\0'; | 
| 779 | } | 
| 780 | |
| 781 | if (nfound != 0) { | 
| 782 | pglob->gl_pathv | 
| 783 | = (char **) xrealloc(pglob->gl_pathv,rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob-> gl_offs : 0) + nfound + 1 ) * sizeof(char *))) | 
| 784 | (pglob->gl_pathc +rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob-> gl_offs : 0) + nfound + 1 ) * sizeof(char *))) | 
| 785 | ((flags & GLOB_DOOFFS) ? pglob->rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob-> gl_offs : 0) + nfound + 1 ) * sizeof(char *))) | 
| 786 | gl_offs : 0) + nfound +rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob-> gl_offs : 0) + nfound + 1 ) * sizeof(char *))) | 
| 787 | 1) * sizeof(char *))rrealloc((pglob->gl_pathv), ((pglob->gl_pathc + ((flags & (1 << 3)) ? pglob-> gl_offs : 0) + nfound + 1 ) * sizeof(char *))); | 
| 788 | |
| 789 | if (flags & GLOB_DOOFFS(1 << 3)) | 
| 790 | while (pglob->gl_pathc < pglob->gl_offs) | 
| 791 | pglob->gl_pathv[pglob->gl_pathc++] = NULL((void*)0); | 
| 792 | |
| 793 | for (; names != NULL((void*)0); names = names->next) | 
| 794 | pglob->gl_pathv[pglob->gl_pathc++] = names->name; | 
| 795 | pglob->gl_pathv[pglob->gl_pathc] = NULL((void*)0); | 
| 796 | |
| 797 | pglob->gl_flags = flags; | 
| 798 | } | 
| 799 | |
| 800 | save = errno(*__errno_location ()); | 
| 801 | if (stream != NULL((void*)0)) { | 
| 802 | if (flags & GLOB_ALTDIRFUNC(1 << 9)) | 
| 803 | (*pglob->gl_closedir) (stream); | 
| 804 | else | 
| 805 | closedir((DIR *) stream); | 
| 806 | } | 
| 807 | __set_errno(save)(*__errno_location ()) = (save); | 
| 808 | |
| 809 | return nfound == 0 ? GLOB_NOMATCH3 : 0; | 
| 810 | } | 
| 811 | |
| 812 | /* librpmio exported interfaces */ | 
| 813 | |
| 814 | int rpmGlob(const char * patterns, int * argcPtr, ARGV_t * argvPtr) | 
| 815 | { | 
| 816 | int ac = 0; | 
| 817 | const char ** av = NULL((void*)0); | 
| 818 | int argc = 0; | 
| 819 | ARGV_t argv = NULL((void*)0); | 
| 820 | char * globRoot = NULL((void*)0); | 
| 821 | const char *home = getenv("HOME")secure_getenv("HOME"); | 
| 822 | int gflags = 0; | 
| 823 | #ifdef ENABLE_NLS1 | 
| 824 | char * old_collate = NULL((void*)0); | 
| 825 | char * old_ctype = NULL((void*)0); | 
| 826 | const char * t; | 
| 827 | #endif | 
| 828 | size_t maxb, nb; | 
| 829 | int i, j; | 
| 830 | int rc; | 
| 831 | |
| 832 | gflags |= GLOB_BRACE(1 << 10); | 
| 833 | |
| 834 | if (home != NULL((void*)0) && strlen(home) > 0) | 
| 835 | gflags |= GLOB_TILDE(1 << 12); | 
| 836 | |
| 837 | /* Can't use argvSplit() here, it doesn't handle whitespace etc escapes */ | 
| 838 | rc = poptParseArgvString(patterns, &ac, &av); | 
| 839 | if (rc) | 
| 840 | return rc; | 
| 841 | |
| 842 | #ifdef ENABLE_NLS1 | 
| 843 | t = setlocale(LC_COLLATE3, NULL((void*)0)); | 
| 844 | if (t) | 
| 845 | old_collate = xstrdup(t)rstrdup((t)); | 
| 846 | t = setlocale(LC_CTYPE0, NULL((void*)0)); | 
| 847 | if (t) | 
| 848 | old_ctype = xstrdup(t)rstrdup((t)); | 
| 849 | (void) setlocale(LC_COLLATE3, "C"); | 
| 850 | (void) setlocale(LC_CTYPE0, "C"); | 
| 851 | #endif | 
| 852 | |
| 853 | if (av != NULL((void*)0)) | 
| 854 | for (j = 0; j < ac; j++) { | 
| 855 | char * globURL; | 
| 856 | const char * path; | 
| 857 | int ut = urlPath(av[j], &path); | 
| 858 | int local = (ut == URL_IS_PATH) || (ut == URL_IS_UNKNOWN); | 
| 859 | size_t plen = strlen(path); | 
| 860 | int flags = gflags; | 
| 861 | int dir_only = (plen > 0 && path[plen-1] == '/'); | 
| 862 | glob_t gl; | 
| 863 | |
| 864 | if (!local || (!rpmIsGlob(av[j], 0) && strchr(path, '~') == NULL((void*)0))) { | 
| 865 | argvAdd(&argv, av[j]); | 
| 866 | continue; | 
| 867 | } | 
| 868 | |
| 869 | if (dir_only) | 
| 870 | flags |= GLOB_ONLYDIR(1 << 13); | 
| 871 | |
| 872 | gl.gl_pathc = 0; | 
| 873 | gl.gl_pathv = NULL((void*)0); | 
| 874 | |
| 875 | rc = glob(av[j], flags, NULL((void*)0), &gl); | 
| 876 | if (rc) | 
| 877 | goto exit; | 
| 878 | |
| 879 | /* XXX Prepend the URL leader for globs that have stripped it off */ | 
| 880 | maxb = 0; | 
| 881 | for (i = 0; i < gl.gl_pathc; i++) { | 
| 882 | if ((nb = strlen(&(gl.gl_pathv[i][0]))) > maxb) | 
| 883 | maxb = nb; | 
| 884 | } | 
| 885 | |
| 886 | nb = ((ut == URL_IS_PATH) ? (path - av[j]) : 0); | 
| 887 | maxb += nb; | 
| 888 | maxb += 1; | 
| 889 | globURL = globRoot = xmalloc(maxb)rmalloc((maxb)); | 
| 890 | |
| 891 | switch (ut) { | 
| 892 | case URL_IS_PATH: | 
| 893 | case URL_IS_DASH: | 
| 894 | strncpy(globRoot, av[j], nb); | 
| 895 | break; | 
| 896 | case URL_IS_HTTPS: | 
| 897 | case URL_IS_HTTP: | 
| 898 | case URL_IS_FTP: | 
| 899 | case URL_IS_HKP: | 
| 900 | case URL_IS_UNKNOWN: | 
| 901 | default: | 
| 902 | break; | 
| 903 | } | 
| 904 | globRoot += nb; | 
| 905 | *globRoot = '\0'; | 
| 906 | |
| 907 | for (i = 0; i < gl.gl_pathc; i++) { | 
| 908 | const char * globFile = &(gl.gl_pathv[i][0]); | 
| 909 | |
| 910 | if (dir_only) { | 
| 911 | struct stat sb; | 
| 912 | if (lstat(gl.gl_pathv[i], &sb) || !S_ISDIR(sb.st_mode)((((sb.st_mode)) & 0170000) == (0040000))) | 
| 913 | continue; | 
| 914 | } | 
| 915 | |
| 916 | if (globRoot > globURL && globRoot[-1] == '/') | 
| 917 | while (*globFile == '/') globFile++; | 
| 918 | strcpy(globRoot, globFile); | 
| 919 | argvAdd(&argv, globURL); | 
| 920 | } | 
| 921 | globfree(&gl); | 
| 922 | free(globURL); | 
| 923 | } | 
| 924 | |
| 925 | argc = argvCount(argv); | 
| 926 | if (argc > 0) { | 
| 927 | if (argvPtr) | 
| 928 | *argvPtr = argv; | 
| 929 | if (argcPtr) | 
| 930 | *argcPtr = argc; | 
| 931 | rc = 0; | 
| 932 | } else | 
| 933 | rc = 1; | 
| 934 | |
| 935 | |
| 936 | exit: | 
| 937 | #ifdef ENABLE_NLS1 | 
| 938 | if (old_collate) { | 
| 939 | (void) setlocale(LC_COLLATE3, old_collate); | 
| 940 | free(old_collate); | 
| 941 | } | 
| 942 | if (old_ctype) { | 
| 943 | (void) setlocale(LC_CTYPE0, old_ctype); | 
| 944 | free(old_ctype); | 
| 945 | } | 
| 946 | #endif | 
| 947 | av = _free(av)rfree((av)); | 
| 948 | if (rc || argvPtr == NULL((void*)0)) { | 
| 949 | argvFree(argv); | 
| 950 | } | 
| 951 | return rc; | 
| 952 | } | 
| 953 | |
| 954 | int rpmIsGlob(const char * pattern, int quote) | 
| 955 | { | 
| 956 | if (!__glob_pattern_p(pattern, quote)) { | 
| 957 | |
| 958 | const char *begin; | 
| 959 | const char *next; | 
| 960 | const char *rest; | 
| 961 | |
| 962 | begin = strchr(pattern, '{'); | 
| 963 | if (begin == NULL((void*)0)) | 
| 964 | return 0; | 
| 965 | /* | 
| 966 | * Find the first sub-pattern and at the same time find the | 
| 967 | * rest after the closing brace. | 
| 968 | */ | 
| 969 | next = next_brace_sub(begin + 1); | 
| 970 | if (next == NULL((void*)0)) | 
| 971 | return 0; | 
| 972 | |
| 973 | /* Now find the end of the whole brace expression. */ | 
| 974 | rest = next; | 
| 975 | while (*rest != '}') { | 
| 976 | rest = next_brace_sub(rest + 1); | 
| 977 | if (rest == NULL((void*)0)) | 
| 978 | return 0; | 
| 979 | } | 
| 980 | /* Now we can be sure that brace expression is well-foermed. */ | 
| 981 | } | 
| 982 | |
| 983 | return 1; | 
| 984 | } |