summaryrefslogtreecommitdiff
path: root/rpmio/rpmglob.c
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2012-05-31 15:37:11 +0300
committerPanu Matilainen <pmatilai@redhat.com>2012-05-31 16:45:26 +0300
commita6821de78318570df9c6a86cd34db4bd037b48a2 (patch)
tree019e0cd741cecc812e2a583c67c8962527e0b004 /rpmio/rpmglob.c
parent077db96e9da9018787b796b0b566f2489c92fe19 (diff)
downloadrpm-a6821de78318570df9c6a86cd34db4bd037b48a2.tar.gz
Split rpmGlob() to a separate source file
- As a preliminary step to hiding our internal glob implementation, split our only glob() user to a source of its own.
Diffstat (limited to 'rpmio/rpmglob.c')
-rw-r--r--rpmio/rpmglob.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/rpmio/rpmglob.c b/rpmio/rpmglob.c
new file mode 100644
index 000000000..d5fadbac6
--- /dev/null
+++ b/rpmio/rpmglob.c
@@ -0,0 +1,148 @@
+#include "system.h"
+
+#include <popt.h>
+#include <rpm/rpmfileutil.h>
+#include <rpm/rpmurl.h>
+
+#include "debug.h"
+
+int rpmGlob(const char * patterns, int * argcPtr, ARGV_t * argvPtr)
+{
+ int ac = 0;
+ const char ** av = NULL;
+ int argc = 0;
+ ARGV_t argv = NULL;
+ char * globRoot = NULL;
+ const char *home = getenv("HOME");
+ int gflags = 0;
+#ifdef ENABLE_NLS
+ char * old_collate = NULL;
+ char * old_ctype = NULL;
+ const char * t;
+#endif
+ size_t maxb, nb;
+ int i, j;
+ int rc;
+
+ if (home != NULL && strlen(home) > 0)
+ gflags |= GLOB_TILDE;
+
+ /* Can't use argvSplit() here, it doesn't handle whitespace etc escapes */
+ rc = poptParseArgvString(patterns, &ac, &av);
+ if (rc)
+ return rc;
+
+#ifdef ENABLE_NLS
+ t = setlocale(LC_COLLATE, NULL);
+ if (t)
+ old_collate = xstrdup(t);
+ t = setlocale(LC_CTYPE, NULL);
+ if (t)
+ old_ctype = xstrdup(t);
+ (void) setlocale(LC_COLLATE, "C");
+ (void) setlocale(LC_CTYPE, "C");
+#endif
+
+ if (av != NULL)
+ for (j = 0; j < ac; j++) {
+ char * globURL;
+ const char * path;
+ int ut = urlPath(av[j], &path);
+ int local = (ut == URL_IS_PATH) || (ut == URL_IS_UNKNOWN);
+ size_t plen = strlen(path);
+ int flags = gflags;
+ int dir_only = (plen > 0 && path[plen-1] == '/');
+ glob_t gl;
+
+ if (!local || (!glob_pattern_p(av[j], 0) && strchr(path, '~') == NULL)) {
+ argvAdd(&argv, av[j]);
+ continue;
+ }
+
+#ifdef GLOB_ONLYDIR
+ if (dir_only)
+ flags |= GLOB_ONLYDIR;
+#endif
+
+ gl.gl_pathc = 0;
+ gl.gl_pathv = NULL;
+
+ rc = glob(av[j], flags, NULL, &gl);
+ if (rc)
+ goto exit;
+
+ /* XXX Prepend the URL leader for globs that have stripped it off */
+ maxb = 0;
+ for (i = 0; i < gl.gl_pathc; i++) {
+ if ((nb = strlen(&(gl.gl_pathv[i][0]))) > maxb)
+ maxb = nb;
+ }
+
+ nb = ((ut == URL_IS_PATH) ? (path - av[j]) : 0);
+ maxb += nb;
+ maxb += 1;
+ globURL = globRoot = xmalloc(maxb);
+
+ switch (ut) {
+ case URL_IS_PATH:
+ case URL_IS_DASH:
+ strncpy(globRoot, av[j], nb);
+ break;
+ case URL_IS_HTTPS:
+ case URL_IS_HTTP:
+ case URL_IS_FTP:
+ case URL_IS_HKP:
+ case URL_IS_UNKNOWN:
+ default:
+ break;
+ }
+ globRoot += nb;
+ *globRoot = '\0';
+
+ for (i = 0; i < gl.gl_pathc; i++) {
+ const char * globFile = &(gl.gl_pathv[i][0]);
+
+ if (dir_only) {
+ struct stat sb;
+ if (lstat(gl.gl_pathv[i], &sb) || !S_ISDIR(sb.st_mode))
+ continue;
+ }
+
+ if (globRoot > globURL && globRoot[-1] == '/')
+ while (*globFile == '/') globFile++;
+ strcpy(globRoot, globFile);
+ argvAdd(&argv, globURL);
+ }
+ globfree(&gl);
+ free(globURL);
+ }
+
+ argc = argvCount(argv);
+ if (argc > 0) {
+ if (argvPtr)
+ *argvPtr = argv;
+ if (argcPtr)
+ *argcPtr = argc;
+ rc = 0;
+ } else
+ rc = 1;
+
+
+exit:
+#ifdef ENABLE_NLS
+ if (old_collate) {
+ (void) setlocale(LC_COLLATE, old_collate);
+ free(old_collate);
+ }
+ if (old_ctype) {
+ (void) setlocale(LC_CTYPE, old_ctype);
+ free(old_ctype);
+ }
+#endif
+ av = _free(av);
+ if (rc || argvPtr == NULL) {
+ argvFree(argv);
+ }
+ return rc;
+}
+