| 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 | } |