Merge "string.h: add __attribute__ ((pure)) to string functions"
diff --git a/libc/Android.mk b/libc/Android.mk
index 1ce2feb..5e41741 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -281,8 +281,12 @@
bionic/ssp.c \
bionic/stubs.c \
bionic/system_properties.c \
+ bionic/tdelete.c \
+ bionic/tdestroy.c \
bionic/time64.c \
+ bionic/tfind.c \
bionic/thread_atexit.c \
+ bionic/tsearch.c \
bionic/utime.c \
bionic/utmp.c \
netbsd/gethnamaddr.c \
diff --git a/libc/bionic/realpath.c b/libc/bionic/realpath.c
index 4cb847b..b909831 100644
--- a/libc/bionic/realpath.c
+++ b/libc/bionic/realpath.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: realpath.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
/*
* Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
*
@@ -27,6 +26,12 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)realpath.c 8.1 (Berkeley) 2/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: release/9.0.0/lib/libc/stdlib/realpath.c 217144 2011-01-08 11:04:30Z kib $");
+
#include <sys/param.h>
#include <sys/stat.h>
@@ -36,23 +41,36 @@
#include <unistd.h>
/*
- * char *realpath(const char *path, char resolved[PATH_MAX]);
- *
* Find the real name of path, by removing all ".", ".." and symlink
* components. Returns (resolved) on success, or (NULL) on failure,
* in which case the path which caused trouble is left in (resolved).
*/
char *
-realpath(const char *path, char resolved[PATH_MAX])
+realpath(const char * __restrict path, char * __restrict resolved)
{
struct stat sb;
char *p, *q, *s;
size_t left_len, resolved_len;
unsigned symlinks;
- int serrno, slen;
+ int m, serrno, slen;
char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
+ if (path == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (path[0] == '\0') {
+ errno = ENOENT;
+ return (NULL);
+ }
serrno = errno;
+ if (resolved == NULL) {
+ resolved = malloc(PATH_MAX);
+ if (resolved == NULL)
+ return (NULL);
+ m = 1;
+ } else
+ m = 0;
symlinks = 0;
if (path[0] == '/') {
resolved[0] = '/';
@@ -63,13 +81,20 @@
left_len = strlcpy(left, path + 1, sizeof(left));
} else {
if (getcwd(resolved, PATH_MAX) == NULL) {
- strlcpy(resolved, ".", PATH_MAX);
+ if (m)
+ free(resolved);
+ else {
+ resolved[0] = '.';
+ resolved[1] = '\0';
+ }
return (NULL);
}
resolved_len = strlen(resolved);
left_len = strlcpy(left, path, sizeof(left));
}
if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
+ if (m)
+ free(resolved);
errno = ENAMETOOLONG;
return (NULL);
}
@@ -85,6 +110,8 @@
p = strchr(left, '/');
s = p ? p : left + left_len;
if (s - left >= sizeof(next_token)) {
+ if (m)
+ free(resolved);
errno = ENAMETOOLONG;
return (NULL);
}
@@ -95,6 +122,8 @@
memmove(left, s + 1, left_len + 1);
if (resolved[resolved_len - 1] != '/') {
if (resolved_len + 1 >= PATH_MAX) {
+ if (m)
+ free(resolved);
errno = ENAMETOOLONG;
return (NULL);
}
@@ -126,6 +155,8 @@
*/
resolved_len = strlcat(resolved, next_token, PATH_MAX);
if (resolved_len >= PATH_MAX) {
+ if (m)
+ free(resolved);
errno = ENAMETOOLONG;
return (NULL);
}
@@ -134,16 +165,23 @@
errno = serrno;
return (resolved);
}
+ if (m)
+ free(resolved);
return (NULL);
}
if (S_ISLNK(sb.st_mode)) {
if (symlinks++ > MAXSYMLINKS) {
+ if (m)
+ free(resolved);
errno = ELOOP;
return (NULL);
}
slen = readlink(resolved, symlink, sizeof(symlink) - 1);
- if (slen < 0)
+ if (slen < 0) {
+ if (m)
+ free(resolved);
return (NULL);
+ }
symlink[slen] = '\0';
if (symlink[0] == '/') {
resolved[1] = 0;
@@ -164,6 +202,8 @@
if (p != NULL) {
if (symlink[slen - 1] != '/') {
if (slen + 1 >= sizeof(symlink)) {
+ if (m)
+ free(resolved);
errno = ENAMETOOLONG;
return (NULL);
}
@@ -172,6 +212,8 @@
}
left_len = strlcat(symlink, left, sizeof(left));
if (left_len >= sizeof(left)) {
+ if (m)
+ free(resolved);
errno = ENAMETOOLONG;
return (NULL);
}
diff --git a/libc/bionic/tdelete.c b/libc/bionic/tdelete.c
new file mode 100644
index 0000000..b64b47a
--- /dev/null
+++ b/libc/bionic/tdelete.c
@@ -0,0 +1,71 @@
+/* $NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ */
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only, lint doesn't grok it.
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: release/9.0.0/lib/libc/stdlib/tdelete.c 108694 2003-01-05 02:43:18Z tjr $");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h>
+
+
+/*
+ * delete node with given key
+ *
+ * vkey: key to be deleted
+ * vrootp: address of the root of the tree
+ * compar: function to carry out node comparisons
+ */
+void *
+tdelete(const void * __restrict vkey, void ** __restrict vrootp,
+ int (*compar)(const void *, const void *))
+{
+ node_t **rootp = (node_t **)vrootp;
+ node_t *p, *q, *r;
+ int cmp;
+
+ if (rootp == NULL || (p = *rootp) == NULL)
+ return NULL;
+
+ while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) {
+ p = *rootp;
+ rootp = (cmp < 0) ?
+ &(*rootp)->llink : /* follow llink branch */
+ &(*rootp)->rlink; /* follow rlink branch */
+ if (*rootp == NULL)
+ return NULL; /* key not found */
+ }
+ r = (*rootp)->rlink; /* D1: */
+ if ((q = (*rootp)->llink) == NULL) /* Left NULL? */
+ q = r;
+ else if (r != NULL) { /* Right link is NULL? */
+ if (r->llink == NULL) { /* D2: Find successor */
+ r->llink = q;
+ q = r;
+ } else { /* D3: Find NULL link */
+ for (q = r->llink; q->llink != NULL; q = r->llink)
+ r = q;
+ r->llink = q->rlink;
+ q->llink = (*rootp)->llink;
+ q->rlink = (*rootp)->rlink;
+ }
+ }
+ free(*rootp); /* D4: Free node */
+ *rootp = q; /* link parent to new node */
+ return p;
+}
diff --git a/libc/bionic/tdestroy.c b/libc/bionic/tdestroy.c
new file mode 100644
index 0000000..70b71f4
--- /dev/null
+++ b/libc/bionic/tdestroy.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h>
+
+/* destroy a tree and free all allocated resources */
+void
+tdestroy(void *root, void (*destroy_func)(void *))
+{
+ node_t *root_node = (node_t *) root;
+ if (root_node == NULL) return;
+ if (root_node->llink)
+ tdestroy(root_node->llink, destroy_func);
+ if (root_node->rlink)
+ tdestroy(root_node->rlink, destroy_func);
+ (*destroy_func)(root_node->key);
+ free(root);
+}
diff --git a/libc/bionic/tfind.c b/libc/bionic/tfind.c
new file mode 100644
index 0000000..7e2bb0c
--- /dev/null
+++ b/libc/bionic/tfind.c
@@ -0,0 +1,48 @@
+/* $NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ */
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only, lint doesn't grok it.
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: release/9.0.0/lib/libc/stdlib/tfind.c 108694 2003-01-05 02:43:18Z tjr $");
+
+#define _SEARCH_PRIVATE
+#include <stdlib.h>
+#include <search.h>
+
+/* find a node, or return 0 */
+void *
+tfind(vkey, vrootp, compar)
+ const void *vkey; /* key to be found */
+ void * const *vrootp; /* address of the tree root */
+ int (*compar)(const void *, const void *);
+{
+ node_t **rootp = (node_t **)vrootp;
+
+ if (rootp == NULL)
+ return NULL;
+
+ while (*rootp != NULL) { /* T1: */
+ int r;
+
+ if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */
+ return *rootp; /* key found */
+ rootp = (r < 0) ?
+ &(*rootp)->llink : /* T3: follow left branch */
+ &(*rootp)->rlink; /* T4: follow right branch */
+ }
+ return NULL;
+}
diff --git a/libc/bionic/tsearch.c b/libc/bionic/tsearch.c
new file mode 100644
index 0000000..4270e6b
--- /dev/null
+++ b/libc/bionic/tsearch.c
@@ -0,0 +1,58 @@
+/* $NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $ */
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only, lint doesn't grok it.
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD: release/9.0.0/lib/libc/stdlib/tsearch.c 108694 2003-01-05 02:43:18Z tjr $");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h>
+
+/* find or insert datum into search tree */
+void *
+tsearch(vkey, vrootp, compar)
+ const void *vkey; /* key to be located */
+ void **vrootp; /* address of tree root */
+ int (*compar)(const void *, const void *);
+{
+ node_t *q;
+ node_t **rootp = (node_t **)vrootp;
+
+ if (rootp == NULL)
+ return NULL;
+
+ while (*rootp != NULL) { /* Knuth's T1: */
+ int r;
+
+ if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */
+ return *rootp; /* we found it! */
+
+ rootp = (r < 0) ?
+ &(*rootp)->llink : /* T3: follow left branch */
+ &(*rootp)->rlink; /* T4: follow right branch */
+ }
+
+ q = malloc(sizeof(node_t)); /* T5: key not found */
+ if (q != 0) { /* make new node */
+ *rootp = q; /* link new node to old */
+ /* LINTED const castaway ok */
+ q->key = (void *)vkey; /* initialize new node */
+ q->llink = q->rlink = NULL;
+ }
+ return q;
+}
diff --git a/libc/include/ar.h b/libc/include/ar.h
new file mode 100644
index 0000000..835290b
--- /dev/null
+++ b/libc/include/ar.h
@@ -0,0 +1,66 @@
+/* $OpenBSD: ar.h,v 1.3 2003/06/02 19:34:12 millert Exp $ */
+/* $NetBSD: ar.h,v 1.4 1994/10/26 00:55:43 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ar.h 8.2 (Berkeley) 1/21/94
+ */
+
+#ifndef _AR_H_
+#define _AR_H_
+
+/* Pre-4BSD archives had these magic numbers in them. */
+#define OARMAG1 0177555
+#define OARMAG2 0177545
+
+#define ARMAG "!<arch>\n" /* ar "magic number" */
+#define SARMAG 8 /* strlen(ARMAG); */
+
+#define AR_EFMT1 "#1/" /* extended format #1 */
+
+struct ar_hdr {
+ char ar_name[16]; /* name */
+ char ar_date[12]; /* modification time */
+ char ar_uid[6]; /* user id */
+ char ar_gid[6]; /* group id */
+ char ar_mode[8]; /* octal file permissions */
+ char ar_size[10]; /* size in bytes */
+#define ARFMAG "`\n"
+ char ar_fmag[2]; /* consistency check */
+};
+
+#endif /* !_AR_H_ */
diff --git a/libc/include/search.h b/libc/include/search.h
new file mode 100644
index 0000000..ed0d216
--- /dev/null
+++ b/libc/include/search.h
@@ -0,0 +1,46 @@
+/*-
+ * Written by J.T. Conklin <jtc@netbsd.org>
+ * Public domain.
+ *
+ * $NetBSD: search.h,v 1.12 1999/02/22 10:34:28 christos Exp $
+ * $FreeBSD: release/9.0.0/include/search.h 105250 2002-10-16 14:29:23Z robert $
+ */
+
+#ifndef _SEARCH_H_
+#define _SEARCH_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#if 0
+#ifndef _SIZE_T_DECLARED
+typedef __size_t size_t;
+#define _SIZE_T_DECLARED
+#endif
+#endif
+
+typedef enum {
+ preorder,
+ postorder,
+ endorder,
+ leaf
+} VISIT;
+
+#ifdef _SEARCH_PRIVATE
+typedef struct node {
+ char *key;
+ struct node *llink, *rlink;
+} node_t;
+#endif
+
+__BEGIN_DECLS
+void *tdelete(const void * __restrict, void ** __restrict,
+ int (*)(const void *, const void *));
+void *tfind(const void *, void * const *,
+ int (*)(const void *, const void *));
+void *tsearch(const void *, void **, int (*)(const void *, const void *));
+void twalk(const void *, void (*)(const void *, VISIT, int));
+void tdestroy(void *, void (*)(void *));
+__END_DECLS
+
+#endif /* !_SEARCH_H_ */
diff --git a/libc/kernel/Android.mk b/libc/kernel/Android.mk
new file mode 100644
index 0000000..6ad9dab
--- /dev/null
+++ b/libc/kernel/Android.mk
@@ -0,0 +1,82 @@
+#
+# Copyright (C) 2012 The Android Open-Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# This file does the bulk of the work to auto post-process kernel headers
+# provided by the device, board, and/or product.
+#
+# The build system exposes several variables for where to find the kernel
+# headers:
+# TARGET_DEVICE_KERNEL_HEADERS is automatically created for the current
+# device being built. It is set as $(TARGET_DEVICE_DIR)/kernel-headers,
+# e.g. device/samsung/tuna/kernel-headers. This directory is not
+# explicitly set by anyone, the build system always adds this subdir.
+#
+# TARGET_BOARD_KERNEL_HEADERS is specified by the BoardConfig.mk file
+# to allow other directories to be included. This is useful if there's
+# some common place where a few headers are being kept for a group
+# of devices. For example, device/<vendor>/common/kernel-headers could
+# contain some headers for several of <vendor>'s devices.
+#
+# TARGET_PRODUCT_KERNEL_HEADERS is generated by the product inheritance
+# graph. This allows architecture products to provide headers for the
+# devices using that architecture. For example,
+# hardware/ti/omap4xxx/omap4.mk will specify
+# PRODUCT_VENDOR_KERNEL_HEADERS variable that specify where the omap4
+# specific headers are, e.g. hardware/ti/omap4xxx/kernel-headers.
+# The build system then combines all the values specified by all the
+# PRODUCT_VENDOR_KERNEL_HEADERS directives in the product inheritance
+# tree and then exports a TARGET_PRODUCT_KERNEL_HEADERS variable.
+#
+# The directories specified in these three variables are scanned for header
+# files (files with .h suffix), processed with the clean_header.py script,
+# and dumped under TARGET_OUT_KERNEL_HEADERS
+# (typically $OUT/obj/kernel-headers). This subdirectory is then
+# automatically added to the include path.
+#
+# The files to be generated are added as a dependency to the
+# all_copied_headers rule to make sure that they are generated before
+# any C/C++ file that may need them.
+#
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+_all_kernel_header_dirs := \
+ $(TARGET_DEVICE_KERNEL_HEADERS) \
+ $(TARGET_BOARD_KERNEL_HEADERS) \
+ $(TARGET_PRODUCT_KERNEL_HEADERS)
+
+define add-kernel-header-dir
+$(eval _headers := $(patsubst $(1)/%.h,%.h,$(shell find $(1)/ -type f -name '*.h')))
+$(eval GEN := $(addprefix $(TARGET_OUT_KERNEL_HEADERS)/,$(_headers)))
+$(GEN) : PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN) : PRIVATE_MODULE := kernel-headers
+$(GEN) : PRIVATE_CUSTOM_TOOL = \
+ $$(LOCAL_PATH)/tools/clean_header.py \
+ -k $(1) -d $$(TARGET_OUT_KERNEL_HEADERS) $$< > $$@
+$(GEN) : $$(LOCAL_PATH)/tools/clean_header.py
+$(GEN) : $$(TARGET_OUT_KERNEL_HEADERS)/%.h : $(1)/%.h
+ $$(transform-generated-source)
+all_copied_headers: $(GEN)
+$(eval GEN :=)
+$(eval _headers :=)
+endef
+
+$(foreach d,$(_all_kernel_header_dirs),\
+ $(eval $(call add-kernel-header-dir,$(d))))
diff --git a/libc/kernel/common/asm-generic/mman-common.h b/libc/kernel/common/asm-generic/mman-common.h
new file mode 100644
index 0000000..157353b
--- /dev/null
+++ b/libc/kernel/common/asm-generic/mman-common.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __ASM_GENERIC_MMAN_COMMON_H
+#define __ASM_GENERIC_MMAN_COMMON_H
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PROT_EXEC 0x4
+#define PROT_SEM 0x8
+#define PROT_NONE 0x0
+#define PROT_GROWSDOWN 0x01000000
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PROT_GROWSUP 0x02000000
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
+#define MAP_TYPE 0x0f
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MAP_FIXED 0x10
+#define MAP_ANONYMOUS 0x20
+#define MAP_UNINITIALIZED 0x0
+#define MS_ASYNC 1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MS_INVALIDATE 2
+#define MS_SYNC 4
+#define MADV_NORMAL 0
+#define MADV_RANDOM 1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MADV_SEQUENTIAL 2
+#define MADV_WILLNEED 3
+#define MADV_DONTNEED 4
+#define MADV_REMOVE 9
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MADV_DONTFORK 10
+#define MADV_DOFORK 11
+#define MADV_HWPOISON 100
+#define MADV_SOFT_OFFLINE 101
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MADV_MERGEABLE 12
+#define MADV_UNMERGEABLE 13
+#define MADV_HUGEPAGE 14
+#define MADV_NOHUGEPAGE 15
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MAP_FILE 0
+#endif
diff --git a/libc/kernel/common/asm-generic/mman.h b/libc/kernel/common/asm-generic/mman.h
index d454921..6eaf900 100644
--- a/libc/kernel/common/asm-generic/mman.h
+++ b/libc/kernel/common/asm-generic/mman.h
@@ -16,38 +16,21 @@
***
****************************************************************************
****************************************************************************/
-#ifndef _ASM_GENERIC_MMAN_H
-#define _ASM_GENERIC_MMAN_H
-#define PROT_READ 0x1
-#define PROT_WRITE 0x2
+#ifndef __ASM_GENERIC_MMAN_H
+#define __ASM_GENERIC_MMAN_H
+#include <asm-generic/mman-common.h>
+#define MAP_GROWSDOWN 0x0100
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define PROT_EXEC 0x4
-#define PROT_SEM 0x8
-#define PROT_NONE 0x0
-#define PROT_GROWSDOWN 0x01000000
+#define MAP_DENYWRITE 0x0800
+#define MAP_EXECUTABLE 0x1000
+#define MAP_LOCKED 0x2000
+#define MAP_NORESERVE 0x4000
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define PROT_GROWSUP 0x02000000
-#define MAP_SHARED 0x01
-#define MAP_PRIVATE 0x02
-#define MAP_TYPE 0x0f
+#define MAP_POPULATE 0x8000
+#define MAP_NONBLOCK 0x10000
+#define MAP_STACK 0x20000
+#define MAP_HUGETLB 0x40000
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define MAP_FIXED 0x10
-#define MAP_ANONYMOUS 0x20
-#define MS_ASYNC 1
-#define MS_INVALIDATE 2
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define MS_SYNC 4
-#define MADV_NORMAL 0
-#define MADV_RANDOM 1
-#define MADV_SEQUENTIAL 2
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define MADV_WILLNEED 3
-#define MADV_DONTNEED 4
-#define MADV_REMOVE 9
-#define MADV_DONTFORK 10
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define MADV_DOFORK 11
-#define MAP_ANON MAP_ANONYMOUS
-#define MAP_FILE 0
+#define MCL_CURRENT 1
+#define MCL_FUTURE 2
#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/unistd/charclass.h b/libc/unistd/charclass.h
new file mode 100644
index 0000000..5edb2c1
--- /dev/null
+++ b/libc/unistd/charclass.h
@@ -0,0 +1,29 @@
+/*
+ * Public domain, 2008, Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * $OpenBSD: charclass.h,v 1.1 2008/10/01 23:04:13 millert Exp $
+ */
+
+/*
+ * POSIX character class support for fnmatch() and glob().
+ */
+static struct cclass {
+ const char *name;
+ int (*isctype)(int);
+} cclasses[] = {
+ { "alnum", isalnum },
+ { "alpha", isalpha },
+ { "blank", isblank },
+ { "cntrl", iscntrl },
+ { "digit", isdigit },
+ { "graph", isgraph },
+ { "lower", islower },
+ { "print", isprint },
+ { "punct", ispunct },
+ { "space", isspace },
+ { "upper", isupper },
+ { "xdigit", isxdigit },
+ { NULL, NULL }
+};
+
+#define NCCLASSES (sizeof(cclasses) / sizeof(cclasses[0]) - 1)
diff --git a/libc/unistd/fnmatch.c b/libc/unistd/fnmatch.c
index ad31c9e..c3d1a3c 100644
--- a/libc/unistd/fnmatch.c
+++ b/libc/unistd/fnmatch.c
@@ -1,205 +1,480 @@
-/* $OpenBSD: fnmatch.c,v 1.13 2006/03/31 05:34:14 deraadt Exp $ */
+/* $OpenBSD: fnmatch.c,v 1.16 2011/12/06 11:47:46 stsp Exp $ */
-/*
- * Copyright (c) 1989, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
+/* Copyright (c) 2011, VMware, Inc.
+ * All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the VMware, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
- * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
- * Compares a filename or pathname to a pattern.
+ * Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
+/* Authored by William A. Rowe Jr. <wrowe; apache.org, vmware.com>, April 2011
+ *
+ * Derived from The Open Group Base Specifications Issue 7, IEEE Std 1003.1-2008
+ * as described in;
+ * http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html
+ *
+ * Filename pattern matches defined in section 2.13, "Pattern Matching Notation"
+ * from chapter 2. "Shell Command Language"
+ * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13
+ * where; 1. A bracket expression starting with an unquoted <circumflex> '^'
+ * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.'
+ * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading
+ * <period> in a filename; 3. a <left-square-bracket> '[' which does not introduce
+ * a valid bracket expression is treated as an ordinary character; 4. a differing
+ * number of consecutive slashes within pattern and string will NOT match;
+ * 5. a trailing '\' in FNM_ESCAPE mode is treated as an ordinary '\' character.
+ *
+ * Bracket expansion defined in section 9.3.5, "RE Bracket Expression",
+ * from chapter 9, "Regular Expressions"
+ * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
+ * with no support for collating symbols, equivalence class expressions or
+ * character class expressions. A partial range expression with a leading
+ * hyphen following a valid range expression will match only the ordinary
+ * <hyphen> and the ending character (e.g. "[a-m-z]" will match characters
+ * 'a' through 'm', a <hyphen> '-', or a 'z').
+ *
+ * Supports BSD extensions FNM_LEADING_DIR to match pattern to the end of one
+ * path segment of string, and FNM_CASEFOLD to ignore alpha case.
+ *
+ * NOTE: Only POSIX/C single byte locales are correctly supported at this time.
+ * Notably, non-POSIX locales with FNM_CASEFOLD produce undefined results,
+ * particularly in ranges of mixed case (e.g. "[A-z]") or spanning alpha and
+ * nonalpha characters within a range.
+ *
+ * XXX comments below indicate porting required for multi-byte character sets
+ * and non-POSIX locale collation orders; requires mbr* APIs to track shift
+ * state of pattern and string (rewinding pattern and string repeatedly).
+ *
+ * Certain parts of the code assume 0x00-0x3F are unique with any MBCS (e.g.
+ * UTF-8, SHIFT-JIS, etc). Any implementation allowing '\' as an alternate
+ * path delimiter must be aware that 0x5C is NOT unique within SHIFT-JIS.
+ */
+
#include <fnmatch.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
-#define EOS '\0'
+#include "charclass.h"
-#define RANGE_MATCH 1
-#define RANGE_NOMATCH 0
-#define RANGE_ERROR (-1)
-
-static int rangematch(const char *, char, int, char **);
-
-int
-fnmatch(const char *pattern, const char *string, int flags)
-{
- const char *stringstart;
- char *newp;
- char c, test;
-
- for (stringstart = string;;)
- switch (c = *pattern++) {
- case EOS:
- if ((flags & FNM_LEADING_DIR) && *string == '/')
- return (0);
- return (*string == EOS ? 0 : FNM_NOMATCH);
- case '?':
- if (*string == EOS)
- return (FNM_NOMATCH);
- if (*string == '/' && (flags & FNM_PATHNAME))
- return (FNM_NOMATCH);
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
- ++string;
- break;
- case '*':
- c = *pattern;
- /* Collapse multiple stars. */
- while (c == '*')
- c = *++pattern;
-
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
-
- /* Optimize for pattern with * at end or before /. */
- if (c == EOS) {
- if (flags & FNM_PATHNAME)
- return ((flags & FNM_LEADING_DIR) ||
- strchr(string, '/') == NULL ?
- 0 : FNM_NOMATCH);
- else
- return (0);
- } else if (c == '/' && (flags & FNM_PATHNAME)) {
- if ((string = strchr(string, '/')) == NULL)
- return (FNM_NOMATCH);
- break;
- }
-
- /* General case, use recursion. */
- while ((test = *string) != EOS) {
- if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
- return (0);
- if (test == '/' && (flags & FNM_PATHNAME))
- break;
- ++string;
- }
- return (FNM_NOMATCH);
- case '[':
- if (*string == EOS)
- return (FNM_NOMATCH);
- if (*string == '/' && (flags & FNM_PATHNAME))
- return (FNM_NOMATCH);
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
-
- switch (rangematch(pattern, *string, flags, &newp)) {
- case RANGE_ERROR:
- /* not a good range, treat as normal text */
- goto normal;
- case RANGE_MATCH:
- pattern = newp;
- break;
- case RANGE_NOMATCH:
- return (FNM_NOMATCH);
- }
- ++string;
- break;
- case '\\':
- if (!(flags & FNM_NOESCAPE)) {
- if ((c = *pattern++) == EOS) {
- c = '\\';
- --pattern;
- }
- }
- /* FALLTHROUGH */
- default:
- normal:
- if (c != *string && !((flags & FNM_CASEFOLD) &&
- (tolower((unsigned char)c) ==
- tolower((unsigned char)*string))))
- return (FNM_NOMATCH);
- ++string;
- break;
- }
- /* NOTREACHED */
-}
+#define RANGE_MATCH 1
+#define RANGE_NOMATCH 0
+#define RANGE_ERROR (-1)
static int
-rangematch(const char *pattern, char test, int flags, char **newp)
+classmatch(const char *pattern, char test, int foldcase, const char **ep)
{
- int negate, ok;
- char c, c2;
+ struct cclass *cc;
+ const char *colon;
+ size_t len;
+ int rval = RANGE_NOMATCH;
+ const char * const mismatch = pattern;
- /*
- * A bracket expression starting with an unquoted circumflex
- * character produces unspecified results (IEEE 1003.2-1992,
- * 3.13.2). This implementation treats it like '!', for
- * consistency with the regular expression syntax.
- * J.T. Conklin (conklin@ngai.kaleida.com)
+ if (*pattern != '[' || pattern[1] != ':') {
+ *ep = mismatch;
+ return(RANGE_ERROR);
+ }
+
+ pattern += 2;
+
+ if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') {
+ *ep = mismatch;
+ return(RANGE_ERROR);
+ }
+ *ep = colon + 2;
+ len = (size_t)(colon - pattern);
+
+ if (foldcase && strncmp(pattern, "upper:]", 7) == 0)
+ pattern = "lower:]";
+ for (cc = cclasses; cc->name != NULL; cc++) {
+ if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') {
+ if (cc->isctype((unsigned char)test))
+ rval = RANGE_MATCH;
+ break;
+ }
+ }
+ if (cc->name == NULL) {
+ /* invalid character class, treat as normal text */
+ *ep = mismatch;
+ rval = RANGE_ERROR;
+ }
+ return(rval);
+}
+
+/* Most MBCS/collation/case issues handled here. Wildcard '*' is not handled.
+ * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over,
+ * however the "\/" sequence is advanced to '/'.
+ *
+ * Both pattern and string are **char to support pointer increment of arbitrary
+ * multibyte characters for the given locale, in a later iteration of this code
+ */
+static int fnmatch_ch(const char **pattern, const char **string, int flags)
+{
+ const char * const mismatch = *pattern;
+ const int nocase = !!(flags & FNM_CASEFOLD);
+ const int escape = !(flags & FNM_NOESCAPE);
+ const int slash = !!(flags & FNM_PATHNAME);
+ int result = FNM_NOMATCH;
+ const char *startch;
+ int negate;
+
+ if (**pattern == '[')
+ {
+ ++*pattern;
+
+ /* Handle negation, either leading ! or ^ operators (never both) */
+ negate = ((**pattern == '!') || (**pattern == '^'));
+ if (negate)
+ ++*pattern;
+
+ /* ']' is an ordinary character at the start of the range pattern */
+ if (**pattern == ']')
+ goto leadingclosebrace;
+
+ while (**pattern)
+ {
+ if (**pattern == ']') {
+ ++*pattern;
+ /* XXX: Fix for MBCS character width */
+ ++*string;
+ return (result ^ negate);
+ }
+
+ if (escape && (**pattern == '\\')) {
+ ++*pattern;
+
+ /* Patterns must be terminated with ']', not EOS */
+ if (!**pattern)
+ break;
+ }
+
+ /* Patterns must be terminated with ']' not '/' */
+ if (slash && (**pattern == '/'))
+ break;
+
+ /* Match character classes. */
+ if (classmatch(*pattern, **string, nocase, pattern)
+ == RANGE_MATCH) {
+ result = 0;
+ continue;
+ }
+
+leadingclosebrace:
+ /* Look at only well-formed range patterns;
+ * "x-]" is not allowed unless escaped ("x-\]")
+ * XXX: Fix for locale/MBCS character width
+ */
+ if (((*pattern)[1] == '-') && ((*pattern)[2] != ']'))
+ {
+ startch = *pattern;
+ *pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2;
+
+ /* NOT a properly balanced [expr] pattern, EOS terminated
+ * or ranges containing a slash in FNM_PATHNAME mode pattern
+ * fall out to to the rewind and test '[' literal code path
+ */
+ if (!**pattern || (slash && (**pattern == '/')))
+ break;
+
+ /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+ if ((**string >= *startch) && (**string <= **pattern))
+ result = 0;
+ else if (nocase && (isupper(**string) || isupper(*startch)
+ || isupper(**pattern))
+ && (tolower(**string) >= tolower(*startch))
+ && (tolower(**string) <= tolower(**pattern)))
+ result = 0;
+
+ ++*pattern;
+ continue;
+ }
+
+ /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+ if ((**string == **pattern))
+ result = 0;
+ else if (nocase && (isupper(**string) || isupper(**pattern))
+ && (tolower(**string) == tolower(**pattern)))
+ result = 0;
+
+ ++*pattern;
+ }
+
+ /* NOT a properly balanced [expr] pattern; Rewind
+ * and reset result to test '[' literal
*/
- if ((negate = (*pattern == '!' || *pattern == '^')))
+ *pattern = mismatch;
+ result = FNM_NOMATCH;
+ }
+ else if (**pattern == '?') {
+ /* Optimize '?' match before unescaping **pattern */
+ if (!**string || (slash && (**string == '/')))
+ return FNM_NOMATCH;
+ result = 0;
+ goto fnmatch_ch_success;
+ }
+ else if (escape && (**pattern == '\\') && (*pattern)[1]) {
+ ++*pattern;
+ }
+
+ /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
+ if (**string == **pattern)
+ result = 0;
+ else if (nocase && (isupper(**string) || isupper(**pattern))
+ && (tolower(**string) == tolower(**pattern)))
+ result = 0;
+
+ /* Refuse to advance over trailing slash or nulls
+ */
+ if (!**string || !**pattern || (slash && ((**string == '/') || (**pattern == '/'))))
+ return result;
+
+fnmatch_ch_success:
+ ++*pattern;
+ ++*string;
+ return result;
+}
+
+
+int fnmatch(const char *pattern, const char *string, int flags)
+{
+ static const char dummystring[2] = {' ', 0};
+ const int escape = !(flags & FNM_NOESCAPE);
+ const int slash = !!(flags & FNM_PATHNAME);
+ const int leading_dir = !!(flags & FNM_LEADING_DIR);
+ const char *strendseg;
+ const char *dummyptr;
+ const char *matchptr;
+ int wild;
+ /* For '*' wild processing only; surpress 'used before initialization'
+ * warnings with dummy initialization values;
+ */
+ const char *strstartseg = NULL;
+ const char *mismatch = NULL;
+ int matchlen = 0;
+
+ if (strnlen(pattern, PATH_MAX) == PATH_MAX ||
+ strnlen(string, PATH_MAX) == PATH_MAX)
+ return (FNM_NOMATCH);
+
+ if (*pattern == '*')
+ goto firstsegment;
+
+ while (*pattern && *string)
+ {
+ /* Pre-decode "\/" which has no special significance, and
+ * match balanced slashes, starting a new segment pattern
+ */
+ if (slash && escape && (*pattern == '\\') && (pattern[1] == '/'))
+ ++pattern;
+ if (slash && (*pattern == '/') && (*string == '/')) {
+ ++pattern;
+ ++string;
+ }
+
+firstsegment:
+ /* At the beginning of each segment, validate leading period behavior.
+ */
+ if ((flags & FNM_PERIOD) && (*string == '.'))
+ {
+ if (*pattern == '.')
++pattern;
+ else if (escape && (*pattern == '\\') && (pattern[1] == '.'))
+ pattern += 2;
+ else
+ return FNM_NOMATCH;
+ ++string;
+ }
- if (flags & FNM_CASEFOLD)
- test = (char)tolower((unsigned char)test);
-
- /*
- * A right bracket shall lose its special meaning and represent
- * itself in a bracket expression if it occurs first in the list.
- * -- POSIX.2 2.8.3.2
+ /* Determine the end of string segment
+ *
+ * Presumes '/' character is unique, not composite in any MBCS encoding
*/
- ok = 0;
- c = *pattern++;
- do {
- if (c == '\\' && !(flags & FNM_NOESCAPE))
- c = *pattern++;
- if (c == EOS)
- return (RANGE_ERROR);
- if (c == '/' && (flags & FNM_PATHNAME))
- return (RANGE_NOMATCH);
- if ((flags & FNM_CASEFOLD))
- c = (char)tolower((unsigned char)c);
- if (*pattern == '-'
- && (c2 = *(pattern+1)) != EOS && c2 != ']') {
- pattern += 2;
- if (c2 == '\\' && !(flags & FNM_NOESCAPE))
- c2 = *pattern++;
- if (c2 == EOS)
- return (RANGE_ERROR);
- if (flags & FNM_CASEFOLD)
- c2 = (char)tolower((unsigned char)c2);
- if (c <= test && test <= c2)
- ok = 1;
- } else if (c == test)
- ok = 1;
- } while ((c = *pattern++) != ']');
+ if (slash) {
+ strendseg = strchr(string, '/');
+ if (!strendseg)
+ strendseg = strchr(string, '\0');
+ }
+ else {
+ strendseg = strchr(string, '\0');
+ }
- *newp = (char *)pattern;
- return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
+ /* Allow pattern '*' to be consumed even with no remaining string to match
+ */
+ while (*pattern)
+ {
+ if ((string > strendseg)
+ || ((string == strendseg) && (*pattern != '*')))
+ break;
+
+ if (slash && ((*pattern == '/')
+ || (escape && (*pattern == '\\')
+ && (pattern[1] == '/'))))
+ break;
+
+ /* Reduce groups of '*' and '?' to n '?' matches
+ * followed by one '*' test for simplicity
+ */
+ for (wild = 0; ((*pattern == '*') || (*pattern == '?')); ++pattern)
+ {
+ if (*pattern == '*') {
+ wild = 1;
+ }
+ else if (string < strendseg) { /* && (*pattern == '?') */
+ /* XXX: Advance 1 char for MBCS locale */
+ ++string;
+ }
+ else { /* (string >= strendseg) && (*pattern == '?') */
+ return FNM_NOMATCH;
+ }
+ }
+
+ if (wild)
+ {
+ strstartseg = string;
+ mismatch = pattern;
+
+ /* Count fixed (non '*') char matches remaining in pattern
+ * excluding '/' (or "\/") and '*'
+ */
+ for (matchptr = pattern, matchlen = 0; 1; ++matchlen)
+ {
+ if ((*matchptr == '\0')
+ || (slash && ((*matchptr == '/')
+ || (escape && (*matchptr == '\\')
+ && (matchptr[1] == '/')))))
+ {
+ /* Compare precisely this many trailing string chars,
+ * the resulting match needs no wildcard loop
+ */
+ /* XXX: Adjust for MBCS */
+ if (string + matchlen > strendseg)
+ return FNM_NOMATCH;
+
+ string = strendseg - matchlen;
+ wild = 0;
+ break;
+ }
+
+ if (*matchptr == '*')
+ {
+ /* Ensure at least this many trailing string chars remain
+ * for the first comparison
+ */
+ /* XXX: Adjust for MBCS */
+ if (string + matchlen > strendseg)
+ return FNM_NOMATCH;
+
+ /* Begin first wild comparison at the current position */
+ break;
+ }
+
+ /* Skip forward in pattern by a single character match
+ * Use a dummy fnmatch_ch() test to count one "[range]" escape
+ */
+ /* XXX: Adjust for MBCS */
+ if (escape && (*matchptr == '\\') && matchptr[1]) {
+ matchptr += 2;
+ }
+ else if (*matchptr == '[') {
+ dummyptr = dummystring;
+ fnmatch_ch(&matchptr, &dummyptr, flags);
+ }
+ else {
+ ++matchptr;
+ }
+ }
+ }
+
+ /* Incrementally match string against the pattern
+ */
+ while (*pattern && (string < strendseg))
+ {
+ /* Success; begin a new wild pattern search
+ */
+ if (*pattern == '*')
+ break;
+
+ if (slash && ((*string == '/')
+ || (*pattern == '/')
+ || (escape && (*pattern == '\\')
+ && (pattern[1] == '/'))))
+ break;
+
+ /* Compare ch's (the pattern is advanced over "\/" to the '/',
+ * but slashes will mismatch, and are not consumed)
+ */
+ if (!fnmatch_ch(&pattern, &string, flags))
+ continue;
+
+ /* Failed to match, loop against next char offset of string segment
+ * until not enough string chars remain to match the fixed pattern
+ */
+ if (wild) {
+ /* XXX: Advance 1 char for MBCS locale */
+ string = ++strstartseg;
+ if (string + matchlen > strendseg)
+ return FNM_NOMATCH;
+
+ pattern = mismatch;
+ continue;
+ }
+ else
+ return FNM_NOMATCH;
+ }
+ }
+
+ if (*string && !((slash || leading_dir) && (*string == '/')))
+ return FNM_NOMATCH;
+
+ if (*pattern && !(slash && ((*pattern == '/')
+ || (escape && (*pattern == '\\')
+ && (pattern[1] == '/')))))
+ return FNM_NOMATCH;
+
+ if (leading_dir && !*pattern && *string == '/')
+ return 0;
+ }
+
+ /* Where both pattern and string are at EOS, declare success
+ */
+ if (!*string && !*pattern)
+ return 0;
+
+ /* pattern didn't match to the end of string */
+ return FNM_NOMATCH;
}
diff --git a/libc/unistd/mmap.c b/libc/unistd/mmap.c
index 848abbb..e097086 100644
--- a/libc/unistd/mmap.c
+++ b/libc/unistd/mmap.c
@@ -32,12 +32,19 @@
extern void* __mmap2(void*, size_t, int, int, int, size_t);
#define MMAP2_SHIFT 12
-void* mmap( void* addr, size_t size, int prot, int flags, int fd, long offset )
+void* mmap(void *addr, size_t size, int prot, int flags, int fd, long offset)
{
- if ( offset & ((1UL << MMAP2_SHIFT)-1) ) {
- errno = EINVAL;
- return MAP_FAILED;
- }
+ void *ret;
- return __mmap2(addr, size, prot, flags, fd, (size_t)offset >> MMAP2_SHIFT);
+ if (offset & ((1UL << MMAP2_SHIFT)-1)) {
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ ret = __mmap2(addr, size, prot, flags, fd, (size_t)offset >> MMAP2_SHIFT);
+
+ if (ret && (flags & (MAP_PRIVATE | MAP_ANONYMOUS)))
+ madvise(ret, size, MADV_MERGEABLE);
+
+ return ret;
}