File klibc-2.0.4-glob.patch of Package klibc

diff -Ndurp klibc-2.0.4/usr/include/glob.h klibc-2.0.4-glob/usr/include/glob.h
--- klibc-2.0.4/usr/include/glob.h	1970-01-01 03:00:00.000000000 +0300
+++ klibc-2.0.4-glob/usr/include/glob.h	2014-10-13 15:55:06.000000000 +0300
@@ -0,0 +1,31 @@
+#ifndef _GLOB_H
+#define _GLOB_H
+
+#include <stddef.h>
+
+typedef struct {
+	size_t gl_pathc;
+	char **gl_pathv;
+	size_t gl_offs;
+	int __dummy1;
+	void *__dummy2[5];
+} glob_t;
+
+int glob(const char *, int, int (*)(const char *, int), glob_t *);
+void globfree(glob_t *);
+
+#define GLOB_ERR      0x01
+#define GLOB_MARK     0x02
+#define GLOB_NOSORT   0x04
+#define GLOB_DOOFFS   0x08
+#define GLOB_NOCHECK  0x10
+#define GLOB_APPEND   0x20
+#define GLOB_NOESCAPE 0x40
+#define	GLOB_PERIOD   0x80
+
+#define GLOB_NOSPACE 1
+#define GLOB_ABORTED 2
+#define GLOB_NOMATCH 3
+#define GLOB_NOSYS   4
+
+#endif
diff -Ndurp klibc-2.0.4/usr/klibc/glob.c klibc-2.0.4-glob/usr/klibc/glob.c
--- klibc-2.0.4/usr/klibc/glob.c	1970-01-01 03:00:00.000000000 +0300
+++ klibc-2.0.4-glob/usr/klibc/glob.c	2014-10-13 18:40:35.420194159 +0300
@@ -0,0 +1,248 @@
+#include <glob.h>
+#include <fnmatch.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stddef.h>
+
+struct match
+{
+	struct match *next;
+	char name[1];
+};
+
+static int is_literal(const char *p, int useesc)
+{
+	int bracket = 0;
+
+	for (; *p; p++) {
+		switch (*p) {
+		case '\\':
+			if (!useesc)
+				break;
+		case '?':
+		case '*':
+			return 0;
+		case '[':
+			bracket = 1;
+			break;
+		case ']':
+			if (!bracket)
+				break;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+static int append(struct match **tail, const char *name, size_t len, int mark)
+{
+	struct match *new = malloc(sizeof(struct match) + len + 1);
+
+	if (!new)
+		return -1;
+	(*tail)->next = new;
+	new->next = NULL;
+	strcpy(new->name, name);
+	if (mark)
+		strcat(new->name, "/");
+	*tail = new;
+	return 0;
+}
+
+static int match_in_dir(const char *d, const char *p, int flags, int (*errfunc)(const char *path, int err), struct match **tail)
+{
+	struct stat st;
+	DIR *dir;
+	char pat[strlen(p) + 1];
+	size_t l = strlen(d);
+	int literal;
+	int fnm_flags= ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) | ((!(flags & GLOB_PERIOD)) ? FNM_PERIOD : 0);
+	int error;
+	char *p2 = strchr(p, '/');
+
+	if (p2) {
+		strcpy(pat, p);
+		pat[p2 - p] = 0;
+		for (; *p2 == '/'; p2++);
+		p = pat;
+	}
+	literal = is_literal(p, !(flags & GLOB_NOESCAPE));
+	if (*d == '/' && !*(d + 1))
+		l = 0;
+
+	/* rely on opendir failing for nondirectory objects */
+	dir = opendir(*d ? d : ".");
+	error = errno;
+	if (!dir) {
+		/* this is not an error -- we let opendir call stat for us */
+		if (error != ENOTDIR) {
+			if (error == EACCES && !*p && !stat(d, &st) && S_ISDIR(st.st_mode)) {
+				if (append(tail, d, l, l))
+					return GLOB_NOSPACE;
+			} else if (errfunc(d, error) || (flags & GLOB_ERR))
+				return GLOB_ABORTED;
+		}
+		return 0;
+	}
+	if (!*p)
+		error = append(tail, d, l, l) ? GLOB_NOSPACE : 0;
+	else
+		for (;;) {
+			struct dirent *de;
+
+			errno = 0;
+			de = readdir(dir);
+			if (de) {
+				unsigned int type = de->d_type << 12;
+				char namebuf[l + de->d_reclen + 2], *name = namebuf;
+
+				if ((!literal && fnmatch(p, de->d_name, fnm_flags)) ||
+				    (literal && strcmp(p, de->d_name)) ||
+				    (p2 && de->d_type && !S_ISDIR(type) && !S_ISLNK(type)))
+					continue;
+				if (*d) {
+					memcpy(name, d, l);
+					name[l] = '/';
+					strcpy(name + l + 1, de->d_name);
+				} else
+					name = de->d_name;
+				if (p2) {
+					error = match_in_dir(name, p2, flags, errfunc, tail);
+					if (error)
+						break;
+				} else {
+					int mark;
+
+					if (flags & GLOB_MARK) {
+						if (de->d_type && !S_ISLNK(type))
+							mark = S_ISDIR(type);
+						else {
+							stat(name, &st);
+							mark = S_ISDIR(st.st_mode);
+						}
+					} else
+						mark = 0;
+					if (append(tail, name, l + de->d_reclen + 1, mark)) {
+						error = GLOB_NOSPACE;
+						break;
+					}
+				}
+			} else {
+				error = errno;
+				if (error)
+					error = (errfunc(d, error) || (flags & GLOB_ERR)) ? GLOB_ABORTED : 0;
+				break;
+			}
+		}
+	closedir(dir);
+	return error;
+}
+
+static int ignore_err(const char *path, int err)
+{
+	return 0;
+}
+
+static void freelist(struct match *head)
+{
+	struct match *match, *next;
+
+	for (match = head->next; match; match = next) {
+		next = match->next;
+		free(match);
+	}
+}
+
+static int sort(const void *a, const void *b)
+{
+	return strcmp(*(const char **)a, *(const char **)b);
+}
+
+int glob(const char *pat, int flags, int (*errfunc)(const char *path, int err), glob_t *g)
+{
+	const char *p = pat, *d;
+	struct match head = { .next = NULL }, *tail = &head;
+	size_t cnt, i;
+	size_t offs;
+	int error;
+
+	if (*p == '/') {
+		for (; *p == '/'; p++);
+		d = "/";
+	} else
+		d = "";
+
+	if (strlen(p) > PATH_MAX)
+		return GLOB_NOSPACE;
+
+	if (!errfunc)
+		errfunc = ignore_err;
+
+	offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0;
+	if (!(flags & GLOB_APPEND)) {
+		g->gl_offs = offs;
+		g->gl_pathc = 0;
+		g->gl_pathv = NULL;
+	}
+
+	if (*p) {
+		error = match_in_dir(d, p, flags, errfunc, &tail);
+		if (error == GLOB_NOSPACE)
+			goto nospace;
+	} else
+		error = 0;
+
+	for (cnt = 0, tail = head.next; tail; tail=tail->next, cnt++);
+	if (!cnt) {
+		if (flags & GLOB_NOCHECK) {
+			tail = &head;
+			if (append(&tail, pat, strlen(pat), 0))
+				return GLOB_NOSPACE;
+			cnt++;
+		} else
+			return GLOB_NOMATCH;
+	}
+
+	if (flags & GLOB_APPEND) {
+		char **pathv = realloc(g->gl_pathv, (offs + g->gl_pathc + cnt + 1) * sizeof(char *));
+
+		if (!pathv)
+			goto nospace;
+		g->gl_pathv = pathv;
+		offs += g->gl_pathc;
+	} else {
+		g->gl_pathv = malloc((offs + cnt + 1) * sizeof(char *));
+		if (!g->gl_pathv)
+			goto nospace;
+		for (i = 0; i < offs; i++)
+			g->gl_pathv[i] = NULL;
+	}
+	for (i = 0, tail = head.next; i < cnt; tail = tail->next, i++)
+		g->gl_pathv[offs + i] = tail->name;
+	g->gl_pathv[offs + i] = NULL;
+	g->gl_pathc += cnt;
+
+	if (!(flags & GLOB_NOSORT))
+		qsort(g->gl_pathv + offs, cnt, sizeof(char *), sort);
+
+	return error;
+
+nospace:
+	freelist(&head);
+	return GLOB_NOSPACE;
+}
+
+void globfree(glob_t *g)
+{
+	size_t i;
+
+	for (i = 0; i < g->gl_pathc; i++)
+		free(g->gl_pathv[g->gl_offs + i] - offsetof(struct match, name));
+	free(g->gl_pathv);
+	g->gl_pathc = 0;
+	g->gl_pathv = NULL;
+}
diff -Ndurp klibc-2.0.4/usr/klibc/Kbuild klibc-2.0.4-glob/usr/klibc/Kbuild
--- klibc-2.0.4/usr/klibc/Kbuild	2014-07-09 18:21:02.000000000 +0300
+++ klibc-2.0.4-glob/usr/klibc/Kbuild	2014-10-13 16:50:35.834557902 +0300
@@ -46,6 +46,7 @@ klib-y += vsnprintf.o snprintf.o vsprint
 	  strxspn.o strspn.o strcspn.o strpbrk.o strsep.o strtok.o \
 	  strtok_r.o \
 	  fnmatch.o \
+	  glob.o \
 	  gethostname.o getdomainname.o getcwd.o \
 	  seteuid.o setegid.o \
 	  getenv.o setenv.o putenv.o __put_env.o unsetenv.o \
openSUSE Build Service is sponsored by