summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2013-11-01 21:54:44 +0000
committerKeith M Wesolowski <wesolows@foobazco.org>2013-11-01 21:54:44 +0000
commit91197d7220bead18a04d4e89692520cf28fbe8b2 (patch)
treecd06ebafbfaafac712db38c2b7b716c6168cc59d /usr/src
parent1db0473d2f1d9999290300fb1abb65d3688d7bc1 (diff)
parent8b1f072cdb7c7ae7c166fc48e2f1988fc5fbb3f4 (diff)
downloadillumos-joyent-91197d7220bead18a04d4e89692520cf28fbe8b2.tar.gz
[illumos-gate merge]
commit 8b1f072cdb7c7ae7c166fc48e2f1988fc5fbb3f4 4233 mptsas topo change buffer overflow commit d33341fb88062a3afe7066acda297c3a1959176a 4263 system/test/zfstest should depend on system/xopen/xcu4 4264 New features should be added to zpool_get.cfg 4276 zfstest should use less common user account than "admin" for ACL tests commit a5229c74bcec7e2b136379c59a46f4b0717fd516 1097 glob(3c) needs to support non-POSIX options 3341 The sftp command should use the native glob()
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/ssh/include/config.h5
-rw-r--r--usr/src/cmd/ssh/include/glob.h112
-rw-r--r--usr/src/head/glob.h123
-rw-r--r--usr/src/lib/libc/port/mapfile-vers6
-rw-r--r--usr/src/lib/libc/port/regex/glob.c1471
-rw-r--r--usr/src/man/man3c/glob.3c264
-rw-r--r--usr/src/pkg/manifests/system-test-zfstest.mf1
-rw-r--r--usr/src/test/zfs-tests/cmd/chg_usr_exec/chg_usr_exec.c6
-rw-r--r--usr/src/test/zfs-tests/tests/functional/acl/acl.cfg4
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg4
-rw-r--r--usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c19
-rw-r--r--usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_smhba.c140
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_smhba.h7
13 files changed, 1702 insertions, 460 deletions
diff --git a/usr/src/cmd/ssh/include/config.h b/usr/src/cmd/ssh/include/config.h
index 884e177d9b..437b120029 100644
--- a/usr/src/cmd/ssh/include/config.h
+++ b/usr/src/cmd/ssh/include/config.h
@@ -4,6 +4,7 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013 Gary Mills
*/
#ifndef _CONFIG_H
@@ -379,10 +380,10 @@ extern "C" {
/* #undef BROKEN_SAVED_UIDS */
/* Define if your system glob() function has the GLOB_ALTDIRFUNC extension */
-/* #undef GLOB_HAS_ALTDIRFUNC */
+#define GLOB_HAS_ALTDIRFUNC 1
/* Define if your system glob() function has gl_matchc options in glob_t */
-/* #undef GLOB_HAS_GL_MATCHC */
+#define GLOB_HAS_GL_MATCHC 1
/*
* Define in your struct dirent expects you to allocate extra space for
diff --git a/usr/src/cmd/ssh/include/glob.h b/usr/src/cmd/ssh/include/glob.h
deleted file mode 100644
index 8918f34cbf..0000000000
--- a/usr/src/cmd/ssh/include/glob.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* $OpenBSD: glob.h,v 1.7 2002/02/17 19:42:21 millert Exp $ */
-/* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */
-
-#ifndef _GLOB_H
-#define _GLOB_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
- * 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. 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.
- *
- * @(#)glob.h 8.1 (Berkeley) 6/2/93
- */
-
-#if !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || \
- !defined(GLOB_HAS_GL_MATCHC)
-
-struct stat;
-typedef struct {
- int gl_pathc; /* Count of total paths so far. */
- int gl_matchc; /* Count of paths matching pattern. */
- int gl_offs; /* Reserved at beginning of gl_pathv. */
- int gl_flags; /* Copy of flags parameter to glob. */
- char **gl_pathv; /* List of paths matching pattern. */
- /* Copy of errfunc parameter to glob. */
- int (*gl_errfunc)(const char *, int);
-
- /*
- * Alternate filesystem access methods for glob; replacement
- * versions of closedir(3), readdir(3), opendir(3), stat(2)
- * and lstat(2).
- */
- void (*gl_closedir)(void *);
- struct dirent *(*gl_readdir)(void *);
- void *(*gl_opendir)(const char *);
- int (*gl_lstat)(const char *, struct stat *);
- int (*gl_stat)(const char *, struct stat *);
-} glob_t;
-
-/* Flags */
-#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
-#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */
-#define GLOB_ERR 0x0004 /* Return on error. */
-#define GLOB_MARK 0x0008 /* Append / to matching directories. */
-#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
-#define GLOB_NOSORT 0x0020 /* Don't sort. */
-
-#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
-#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
-#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
-#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
-#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
-#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
-#define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */
-#define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */
-
-/* Error values returned by glob(3) */
-#define GLOB_NOSPACE (-1) /* Malloc call failed. */
-#define GLOB_ABORTED (-2) /* Unignored error. */
-#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */
-#define GLOB_NOSYS (-4) /* Function not supported. */
-#define GLOB_ABEND GLOB_ABORTED
-
-int glob(const char *, int, int (*)(const char *, int), glob_t *);
-void globfree(glob_t *);
-
-#endif /* !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) ||
- !defined(GLOB_HAS_GL_MATCHC */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _GLOB_H */
diff --git a/usr/src/head/glob.h b/usr/src/head/glob.h
index c10629850e..9468d5f6dd 100644
--- a/usr/src/head/glob.h
+++ b/usr/src/head/glob.h
@@ -19,38 +19,105 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright 1985, 1992 by Mortice Kern Systems Inc. All rights reserved.
*/
/*
- * Copyright 1985, 1992 by Mortice Kern Systems Inc. All rights reserved.
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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.
+ *
+ * @(#)glob.h 8.1 (Berkeley) 6/2/93
+ */
+
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ * Copyright (c) 2013 Gary Mills
*/
#ifndef _GLOB_H
#define _GLOB_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/feature_tests.h>
#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct glob_t {
- size_t gl_pathc; /* Count of paths matched by pattern */
- char **gl_pathv; /* List of matched pathnames */
- size_t gl_offs; /* # of slots reserved in gl_pathv */
- /* following are internal to the implementation */
- char **gl_pathp; /* gl_pathv + gl_offs */
- int gl_pathn; /* # of elements allocated */
+ /*
+ * Members specified by POSIX
+ */
+ size_t gl_pathc; /* Total count of paths matched by pattern */
+ char **gl_pathv; /* List of matched pathnames */
+ size_t gl_offs; /* # of slots reserved in gl_pathv */
+
+ /*
+ * Internal-use members:
+ *
+ * NB: The next two members are carried in both the
+ * libc backward compatibility wrapper functions and
+ * the extended functions.
+ */
+ char **gl_pathp; /* gl_pathv + gl_offs */
+ int gl_pathn; /* # of elements allocated */
+
+ /*
+ * Non-POSIX extensions
+ *
+ * NB: The following members are not carried in
+ * the libc backward compatibility wrapper functions.
+ */
+ int gl_matchc; /* Count of paths matching pattern. */
+ int gl_flags; /* Copy of flags parameter to glob. */
+ struct stat **gl_statv; /* Stat entries corresponding to gl_pathv */
+
+ /*
+ * Alternate filesystem access methods for glob; replacement
+ * versions of closedir(3), readdir(3), opendir(3), stat(2)
+ * and lstat(2).
+ */
+ void (*gl_closedir)(void *);
+ struct dirent *(*gl_readdir)(void *);
+ void *(*gl_opendir)(const char *);
+ int (*gl_lstat)(const char *, struct stat *);
+ int (*gl_stat)(const char *, struct stat *);
} glob_t;
/*
- * "flags" argument to glob function.
+ * POSIX "flags" argument to glob function.
*/
#define GLOB_ERR 0x0001 /* Don't continue on directory error */
#define GLOB_MARK 0x0002 /* Mark directories with trailing / */
@@ -61,21 +128,49 @@ typedef struct glob_t {
#define GLOB_NOESCAPE 0x0040 /* Backslashes do not quote M-chars */
/*
+ * Non-POSIX "flags" argument to glob function, from OpenBSD.
+ */
+#if !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__)
+#define GLOB_POSIX 0x007F /* All POSIX flags */
+#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
+#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
+#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
+#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
+#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
+#define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */
+#define GLOB_KEEPSTAT 0x4000 /* Retain stat data for paths in gl_statv. */
+#define GLOB_ALTDIRFUNC 0x8000 /* Use alternately specified directory funcs. */
+#endif /* !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__) */
+
+/*
* Error returns from "glob"
*/
#define GLOB_NOSYS (-4) /* function not supported (XPG4) */
#define GLOB_NOMATCH (-3) /* Pattern does not match */
#define GLOB_NOSPACE (-2) /* Not enough memory */
#define GLOB_ABORTED (-1) /* GLOB_ERR set or errfunc return!=0 */
+#define GLOB_ABEND GLOB_ABORTED /* backward compatibility */
+
+#ifdef __PRAGMA_REDEFINE_EXTNAME
+#pragma redefine_extname glob _glob_ext
+#pragma redefine_extname globfree _globfree_ext
+#else /* __PRAGMA_REDEFINE_EXTNAME */
+#define glob _glob_ext
+#define globfree _globfree_ext
+#endif /* __PRAGMA_REDEFINE_EXTNAME */
#if defined(__STDC__)
+
extern int glob(const char *_RESTRICT_KYWD, int, int(*)(const char *, int),
glob_t *_RESTRICT_KYWD);
extern void globfree(glob_t *);
-#else
+
+#else /* __STDC__ */
+
extern int glob();
extern void globfree();
-#endif
+
+#endif /* __STDC__ */
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index b40d3c419f..585c47328d 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -93,6 +93,12 @@ $if _x86 && _ELF64
$add amd64
$endif
+SYMBOL_VERSION ILLUMOS_0.7 { # Illumos additions
+ protected:
+ _glob_ext;
+ _globfree_ext;
+} ILLUMOS_0.6;
+
SYMBOL_VERSION ILLUMOS_0.6 { # Illumos additions
protected:
getloginx;
diff --git a/usr/src/lib/libc/port/regex/glob.c b/usr/src/lib/libc/port/regex/glob.c
index c557b6f44d..425f9c8724 100644
--- a/usr/src/lib/libc/port/regex/glob.c
+++ b/usr/src/lib/libc/port/regex/glob.c
@@ -1,299 +1,1336 @@
/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2013 Gary Mills
*/
-
+/* $OpenBSD: glob.c,v 1.39 2012/01/20 07:09:42 tedu Exp $ */
/*
- * This code is MKS code ported to Solaris originally with minimum
- * modifications so that upgrades from MKS would readily integrate.
- * The MKS basis for this modification was:
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
*
- * $Id: glob.c 1.31 1994/04/07 22:50:43 mark
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
*
- * Additional modifications have been made to this code to make it
- * 64-bit clean.
+ * 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.
*/
/*
- * glob, globfree -- POSIX.2 compatible file name expansion routines.
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
*
- * Copyright 1985, 1991 by Mortice Kern Systems Inc. All rights reserved.
+ * Optional extra services, controlled by flags not defined by POSIX:
*
- * Written by Eric Gisin.
+ * GLOB_QUOTE:
+ * Escaping convention: \ inhibits any special meaning the following
+ * character might have (except \ at end of string is retained).
+ * GLOB_MAGCHAR:
+ * Set in gl_flags if pattern contained a globbing character.
+ * GLOB_NOMAGIC:
+ * Same as GLOB_NOCHECK, but it will only append pattern if it did
+ * not contain any magic characters. [Used in csh style globbing]
+ * GLOB_ALTDIRFUNC:
+ * Use alternately specified directory access functions.
+ * GLOB_TILDE:
+ * expand ~user/foo to the /home/dir/of/user/foo
+ * GLOB_BRACE:
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
+ * gl_matchc:
+ * Number of matches in the current invocation of glob.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+#include "lint.h"
-#pragma weak _glob = glob
-#pragma weak _globfree = globfree
+#include <sys/param.h>
+#include <sys/stat.h>
-#include "lint.h"
-#include <stdio.h>
-#include <unistd.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <glob.h>
#include <limits.h>
+#include <pwd.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <glob.h>
-#include <errno.h>
-#include <fnmatch.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
-#define GLOB__CHECK 0x80 /* stat generated paths */
+/*
+ * This is the legacy glob_t prior to illumos enhancement 1097,
+ * used when old programs call the old libc glob functions.
+ * (New programs call the _glob_ext, _globfree_ext functions.)
+ * This struct should be considered "carved in stone".
+ */
+typedef struct old_glob {
+ size_t gl_pathc; /* Count of paths matched by pattern */
+ char **gl_pathv; /* List of matched pathnames */
+ size_t gl_offs; /* # of slots reserved in gl_pathv */
+ /* following are internal to the implementation */
+ char **gl_pathp; /* gl_pathv + gl_offs */
+ int gl_pathn; /* # of elements allocated */
+} old_glob_t;
+
+/*
+ * For old programs, the external names need to be the old names:
+ * glob() and globfree() . We've redefined those already to
+ * _glob_ext() and _globfree_ext() . Now redefine old_glob()
+ * and old_globfree() to glob() and globfree() .
+ */
+#ifdef __PRAGMA_REDEFINE_EXTNAME
+#pragma redefine_extname old_glob glob
+#pragma redefine_extname old_globfree globfree
+#endif /* __PRAGMA_REDEFINE_EXTNAME */
+extern int old_glob(const char *, int, int (*)(const char *, int),
+ old_glob_t *);
+extern void old_globfree(old_glob_t *);
-#define INITIAL 8 /* initial pathv allocation */
-#define NULLCPP ((char **)0) /* Null char ** */
-#define NAME_MAX 1024 /* something large */
+#define DOLLAR '$'
+#define DOT '.'
+#define EOS '\0'
+#define LBRACKET '['
+#define NOT '!'
+#define QUESTION '?'
+#define QUOTE '\\'
+#define RANGE '-'
+#define RBRACKET ']'
+#define SEP '/'
+#define STAR '*'
+#define TILDE '~'
+#define UNDERSCORE '_'
+#define LBRACE '{'
+#define RBRACE '}'
+#define SLASH '/'
+#define COMMA ','
+#define COLON ':'
-static int globit(size_t, const char *, glob_t *, int,
- int (*)(const char *, int), char **);
-static int pstrcmp(const void *, const void *);
-static int append(glob_t *, const char *);
+#define M_QUOTE 0x800000
+#define M_PROTECT 0x400000
+
+typedef struct wcat {
+ wchar_t w_wc;
+ uint_t w_at;
+} wcat_t;
+
+#define M_ALL '*' /* Plus M_QUOTE */
+#define M_END ']' /* Plus M_QUOTE */
+#define M_NOT '!' /* Plus M_QUOTE */
+#define M_ONE '?' /* Plus M_QUOTE */
+#define M_RNG '-' /* Plus M_QUOTE */
+#define M_SET '[' /* Plus M_QUOTE */
+#define M_CLASS ':' /* Plus M_QUOTE */
+#define ismeta(c) (((c).w_at&M_QUOTE) != 0)
+
+#define INITIAL 8 /* initial pathv allocation */
+
+#define GLOB_LIMIT_MALLOC 65536
+#define GLOB_LIMIT_STAT 2048
+#define GLOB_LIMIT_READDIR 16384
+
+/* Limit of recursion during matching attempts. */
+#define GLOB_LIMIT_RECUR 64
+
+struct glob_lim {
+ size_t glim_malloc;
+ size_t glim_stat;
+ size_t glim_readdir;
+};
+
+struct glob_path_stat {
+ char *gps_path;
+ struct stat *gps_stat;
+};
+
+static int compare(const void *, const void *);
+static int compare_gps(const void *, const void *);
+static int g_Ctoc(const wcat_t *, char *, uint_t);
+static int g_lstat(wcat_t *, struct stat *, glob_t *);
+static DIR *g_opendir(wcat_t *, glob_t *);
+static wcat_t *g_strchr(const wcat_t *, wchar_t);
+static int g_stat(wcat_t *, struct stat *, glob_t *);
+static int glob0(const wcat_t *, glob_t *, struct glob_lim *,
+ int (*)(const char *, int));
+static int glob1(wcat_t *, wcat_t *, glob_t *, struct glob_lim *,
+ int (*)(const char *, int));
+static int glob2(wcat_t *, wcat_t *, wcat_t *, wcat_t *, wcat_t *,
+ wcat_t *, glob_t *, struct glob_lim *,
+ int (*)(const char *, int));
+static int glob3(wcat_t *, wcat_t *, wcat_t *, wcat_t *, wcat_t *,
+ wcat_t *, wcat_t *, glob_t *, struct glob_lim *,
+ int (*)(const char *, int));
+static int globextend(const wcat_t *, glob_t *, struct glob_lim *,
+ struct stat *);
+static
+const wcat_t *globtilde(const wcat_t *, wcat_t *, size_t, glob_t *);
+static int globexp1(const wcat_t *, glob_t *, struct glob_lim *,
+ int (*)(const char *, int));
+static int globexp2(const wcat_t *, const wcat_t *, glob_t *,
+ struct glob_lim *, int (*)(const char *, int));
+static int match(wcat_t *, wcat_t *, wcat_t *, int);
/*
- * Free all space consumed by glob.
+ * Extended glob() function, selected by #pragma redefine_extname
+ * in glob.h with the external name _glob_ext() .
*/
-void
-globfree(glob_t *gp)
+int
+_glob_ext(const char *pattern, int flags, int (*errfunc)(const char *, int),
+ glob_t *pglob)
{
- size_t i;
+ const char *patnext;
+ int n;
+ size_t patlen;
+ wchar_t c;
+ wcat_t *bufnext, *bufend, patbuf[MAXPATHLEN];
+ struct glob_lim limit = { 0, 0, 0 };
- if (gp->gl_pathv == 0)
- return;
+ if ((patlen = strnlen(pattern, PATH_MAX)) == PATH_MAX)
+ return (GLOB_NOMATCH);
- for (i = gp->gl_offs; i < gp->gl_offs + gp->gl_pathc; ++i)
- free(gp->gl_pathv[i]);
- free((void *)gp->gl_pathv);
+ patnext = pattern;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathn = 0;
+ pglob->gl_pathv = NULL;
+ if ((flags & GLOB_KEEPSTAT) != 0)
+ pglob->gl_statv = NULL;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_offs = 0;
+ }
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_matchc = 0;
+
+ if (pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX ||
+ pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1)
+ return (GLOB_NOSPACE);
- gp->gl_pathc = 0;
- gp->gl_pathv = NULLCPP;
+ bufnext = patbuf;
+ bufend = bufnext + MAXPATHLEN - 1;
+ patlen += 1;
+ if (flags & GLOB_NOESCAPE) {
+ while (bufnext < bufend) {
+ if ((n = mbtowc(&c, patnext, patlen)) > 0) {
+ patnext += n;
+ patlen -= n;
+ bufnext->w_at = 0;
+ (bufnext++)->w_wc = c;
+ } else if (n == 0) {
+ break;
+ } else {
+ return (GLOB_NOMATCH);
+ }
+ }
+ } else {
+ /* Protect the quoted characters. */
+ while (bufnext < bufend) {
+ if ((n = mbtowc(&c, patnext, patlen)) > 0) {
+ patnext += n;
+ patlen -= n;
+ if (c == QUOTE) {
+ n = mbtowc(&c, patnext, patlen);
+ if (n < 0)
+ return (GLOB_NOMATCH);
+ if (n > 0) {
+ patnext += n;
+ patlen -= n;
+ }
+ if (n == 0)
+ c = QUOTE;
+ bufnext->w_at = M_PROTECT;
+ (bufnext++)->w_wc = c;
+ } else {
+ bufnext->w_at = 0;
+ (bufnext++)->w_wc = c;
+ }
+ } else if (n == 0) {
+ break;
+ } else {
+ return (GLOB_NOMATCH);
+ }
+ }
+ }
+ bufnext->w_at = 0;
+ bufnext->w_wc = EOS;
+
+ if (flags & GLOB_BRACE)
+ return (globexp1(patbuf, pglob, &limit, errfunc));
+ else
+ return (glob0(patbuf, pglob, &limit, errfunc));
}
/*
- * Do filename expansion.
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
*/
-int
-glob(const char *pattern, int flags,
- int (*errfn)(const char *, int), glob_t *gp)
+static int
+globexp1(const wcat_t *pattern, glob_t *pglob, struct glob_lim *limitp,
+ int (*errfunc)(const char *, int))
{
- int rv;
- size_t i;
- size_t ipathc;
- char *path;
+ const wcat_t *ptr = pattern;
- if ((flags & GLOB_DOOFFS) == 0)
- gp->gl_offs = 0;
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0].w_wc == LBRACE && pattern[1].w_wc == RBRACE &&
+ pattern[2].w_wc == EOS)
+ return (glob0(pattern, pglob, limitp, errfunc));
- if (!(flags & GLOB_APPEND)) {
- gp->gl_pathc = 0;
- gp->gl_pathn = gp->gl_offs + INITIAL;
- gp->gl_pathv = (char **)malloc(sizeof (char *) * gp->gl_pathn);
+ if ((ptr = (const wcat_t *) g_strchr(ptr, LBRACE)) != NULL)
+ return (globexp2(ptr, pattern, pglob, limitp, errfunc));
- if (gp->gl_pathv == NULLCPP)
- return (GLOB_NOSPACE);
- gp->gl_pathp = gp->gl_pathv + gp->gl_offs;
+ return (glob0(pattern, pglob, limitp, errfunc));
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int
+globexp2(const wcat_t *ptr, const wcat_t *pattern, glob_t *pglob,
+ struct glob_lim *limitp, int (*errfunc)(const char *, int))
+{
+ int i, rv;
+ wcat_t *lm, *ls;
+ const wcat_t *pe, *pm, *pl;
+ wcat_t patbuf[MAXPATHLEN];
+
+ /* copy part up to the brace */
+ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+ ;
+ lm->w_at = 0;
+ lm->w_wc = EOS;
+ ls = lm;
+
+ /* Find the balanced brace */
+ for (i = 0, pe = ++ptr; pe->w_wc != EOS; pe++)
+ if (pe->w_wc == LBRACKET) {
+ /* Ignore everything between [] */
+ for (pm = pe++; pe->w_wc != RBRACKET &&
+ pe->w_wc != EOS; pe++)
+ ;
+ if (pe->w_wc == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pe = pm;
+ }
+ } else if (pe->w_wc == LBRACE) {
+ i++;
+ } else if (pe->w_wc == RBRACE) {
+ if (i == 0)
+ break;
+ i--;
+ }
+
+ /* Non matching braces; just glob the pattern */
+ if (i != 0 || pe->w_wc == EOS)
+ return (glob0(patbuf, pglob, limitp, errfunc));
+
+ for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
+ switch (pm->w_wc) {
+ case LBRACKET:
+ /* Ignore everything between [] */
+ for (pl = pm++; pm->w_wc != RBRACKET && pm->w_wc != EOS;
+ pm++)
+ ;
+ if (pm->w_wc == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pm = pl;
+ }
+ break;
+
+ case LBRACE:
+ i++;
+ break;
+
+ case RBRACE:
+ if (i) {
+ i--;
+ break;
+ }
+ /* FALLTHROUGH */
+ case COMMA:
+ if (i && pm->w_wc == COMMA)
+ break;
+ else {
+ /* Append the current string */
+ for (lm = ls; (pl < pm); *lm++ = *pl++)
+ ;
+
+ /*
+ * Append the rest of the pattern after the
+ * closing brace
+ */
+ for (pl = pe + 1;
+ (*lm++ = *pl++).w_wc != EOS; /* */)
+ ;
+
+ /* Expand the current pattern */
+ rv = globexp1(patbuf, pglob, limitp, errfunc);
+ if (rv && rv != GLOB_NOMATCH)
+ return (rv);
- for (i = 0; i < gp->gl_offs; ++i)
- gp->gl_pathv[i] = NULL;
+ /* move after the comma, to the next string */
+ pl = pm + 1;
+ }
+ break;
+
+ default:
+ break;
+ }
}
+ return (0);
+}
- if ((path = malloc(strlen(pattern)+1)) == NULL)
- return (GLOB_NOSPACE);
- ipathc = gp->gl_pathc;
- rv = globit(0, pattern, gp, flags, errfn, &path);
- if (rv == GLOB_ABORTED) {
+/*
+ * expand tilde from the passwd file.
+ */
+static const wcat_t *
+globtilde(const wcat_t *pattern, wcat_t *patbuf, size_t patbuf_len,
+ glob_t *pglob)
+{
+ struct passwd *pwd;
+ char *h;
+ const wcat_t *p;
+ wcat_t *b, *eb, *q;
+ int n;
+ size_t lenh;
+ wchar_t c;
+
+ if (pattern->w_wc != TILDE || !(pglob->gl_flags & GLOB_TILDE))
+ return (pattern);
+
+ /* Copy up to the end of the string or / */
+ eb = &patbuf[patbuf_len - 1];
+ for (p = pattern + 1, q = patbuf;
+ q < eb && p->w_wc != EOS && p->w_wc != SLASH; *q++ = *p++)
+ ;
+
+ q->w_at = 0;
+ q->w_wc = EOS;
+
+ /* What to do if patbuf is full? */
+
+ if (patbuf[0].w_wc == EOS) {
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME
+ * first and then trying the password file
+ */
+ if (issetugid() != 0)
+ return (pattern);
+ if ((h = getenv("HOME")) == NULL) {
+ if ((pwd = getpwuid(getuid())) == NULL)
+ return (pattern);
+ else
+ h = pwd->pw_dir;
+ }
+ } else {
/*
- * User's error function returned non-zero, or GLOB_ERR was
- * set, and we encountered a directory we couldn't search.
+ * Expand a ~user
*/
- free(path);
- return (GLOB_ABORTED);
+ if ((pwd = getpwnam((char *)patbuf)) == NULL)
+ return (pattern);
+ else
+ h = pwd->pw_dir;
}
- i = gp->gl_pathc - ipathc;
- if (i >= 1 && !(flags & GLOB_NOSORT)) {
- qsort((char *)(gp->gl_pathp+ipathc), i, sizeof (char *),
- pstrcmp);
- }
- if (i == 0) {
- if (flags & GLOB_NOCHECK)
- (void) append(gp, pattern);
- else
- rv = GLOB_NOMATCH;
+ /* Copy the home directory */
+ lenh = strlen(h) + 1;
+ for (b = patbuf; b < eb && *h != EOS; b++) {
+ if ((n = mbtowc(&c, h, lenh)) > 0) {
+ h += n;
+ lenh -= n;
+ b->w_at = 0;
+ b->w_wc = c;
+ } else if (n < 0) {
+ return (pattern);
+ } else {
+ break;
+ }
}
- gp->gl_pathp[gp->gl_pathc] = NULL;
- free(path);
- return (rv);
+ /* Append the rest of the pattern */
+ while (b < eb && (*b++ = *p++).w_wc != EOS)
+ ;
+ b->w_at = 0;
+ b->w_wc = EOS;
+
+ return (patbuf);
}
+static int
+g_charclass(const wcat_t **patternp, wcat_t **bufnextp)
+{
+ const wcat_t *pattern = *patternp + 1;
+ wcat_t *bufnext = *bufnextp;
+ const wcat_t *colon;
+ char cbuf[MB_LEN_MAX + 32];
+ wctype_t cc;
+ size_t len;
+
+ if ((colon = g_strchr(pattern, COLON)) == NULL ||
+ colon[1].w_wc != RBRACKET)
+ return (1); /* not a character class */
+
+ len = (size_t)(colon - pattern);
+ if (len + MB_LEN_MAX + 1 > sizeof (cbuf))
+ return (-1); /* invalid character class */
+ {
+ wchar_t w;
+ const wcat_t *s1 = pattern;
+ char *s2 = cbuf;
+ size_t n = len;
+
+ /* Copy the string. */
+ while (n > 0) {
+ w = (s1++)->w_wc;
+ /* Character class names must be ASCII. */
+ if (iswascii(w)) {
+ n--;
+ *s2++ = w;
+ } else {
+ return (-1); /* invalid character class */
+ }
+ }
+ *s2 = EOS;
+ }
+ if ((cc = wctype(cbuf)) == 0)
+ return (-1); /* invalid character class */
+ bufnext->w_at = M_QUOTE;
+ (bufnext++)->w_wc = M_CLASS;
+ bufnext->w_at = 0;
+ (bufnext++)->w_wc = cc;
+ *bufnextp = bufnext;
+ *patternp += len + 3;
+
+ return (0);
+}
/*
- * Recursive routine to match glob pattern, and walk directories.
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred. It is not an error
+ * to find no matches.
*/
-int
-globit(size_t dend, const char *sp, glob_t *gp, int flags,
- int (*errfn)(const char *, int), char **path)
+static int
+glob0(const wcat_t *pattern, glob_t *pglob, struct glob_lim *limitp,
+ int (*errfunc)(const char *, int))
{
- size_t n;
- size_t m;
- ssize_t end = 0; /* end of expanded directory */
- char *pat = (char *)sp; /* pattern component */
- char *dp = (*path) + dend;
- int expand = 0; /* path has pattern */
- char *cp;
- struct stat64 sb;
- DIR *dirp;
- struct dirent64 *d;
- int err;
+ const wcat_t *qpatnext;
+ int err, oldpathc;
+ wchar_t c;
+ int a;
+ wcat_t *bufnext, patbuf[MAXPATHLEN];
- for (;;)
- switch (*dp++ = *(unsigned char *)sp++) {
- case '\0': /* end of source path */
- if (expand)
- goto Expand;
- else {
- if (!(flags & GLOB_NOCHECK) ||
- flags & (GLOB__CHECK|GLOB_MARK))
- if (stat64(*path, &sb) < 0) {
- return (0);
- }
- if (flags & GLOB_MARK && S_ISDIR(sb.st_mode)) {
- *dp = '\0';
- *--dp = '/';
+ qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
+ oldpathc = pglob->gl_pathc;
+ bufnext = patbuf;
+
+ /*
+ * We don't need to check for buffer overflow any more.
+ * The pattern has already been copied to an internal buffer.
+ */
+ while ((a = qpatnext->w_at), (c = (qpatnext++)->w_wc) != EOS) {
+ switch (c) {
+ case LBRACKET:
+ if (a != 0) {
+ bufnext->w_at = a;
+ (bufnext++)->w_wc = c;
+ break;
+ }
+ a = qpatnext->w_at;
+ c = qpatnext->w_wc;
+ if (a == 0 && c == NOT)
+ ++qpatnext;
+ if (qpatnext->w_wc == EOS ||
+ g_strchr(qpatnext+1, RBRACKET) == NULL) {
+ bufnext->w_at = 0;
+ (bufnext++)->w_wc = LBRACKET;
+ if (a == 0 && c == NOT)
+ --qpatnext;
+ break;
+ }
+ bufnext->w_at = M_QUOTE;
+ (bufnext++)->w_wc = M_SET;
+ if (a == 0 && c == NOT) {
+ bufnext->w_at = M_QUOTE;
+ (bufnext++)->w_wc = M_NOT;
+ }
+ a = qpatnext->w_at;
+ c = (qpatnext++)->w_wc;
+ do {
+ if (a == 0 && c == LBRACKET &&
+ qpatnext->w_wc == COLON) {
+ do {
+ err = g_charclass(&qpatnext,
+ &bufnext);
+ if (err)
+ break;
+ a = qpatnext->w_at;
+ c = (qpatnext++)->w_wc;
+ } while (a == 0 && c == LBRACKET &&
+ qpatnext->w_wc == COLON);
+ if (err == -1 &&
+ !(pglob->gl_flags & GLOB_NOCHECK))
+ return (GLOB_NOMATCH);
+ if (a == 0 && c == RBRACKET)
+ break;
}
- if (append(gp, *path) < 0) {
- return (GLOB_NOSPACE);
+ bufnext->w_at = a;
+ (bufnext++)->w_wc = c;
+ if (qpatnext->w_at == 0 &&
+ qpatnext->w_wc == RANGE) {
+ a = qpatnext[1].w_at;
+ c = qpatnext[1].w_wc;
+ if (qpatnext[1].w_at != 0 ||
+ qpatnext[1].w_wc != RBRACKET) {
+ bufnext->w_at = M_QUOTE;
+ (bufnext++)->w_wc = M_RNG;
+ bufnext->w_at = a;
+ (bufnext++)->w_wc = c;
+ qpatnext += 2;
+ }
}
- return (0);
+ a = qpatnext->w_at;
+ c = (qpatnext++)->w_wc;
+ } while (a != 0 || c != RBRACKET);
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ bufnext->w_at = M_QUOTE;
+ (bufnext++)->w_wc = M_END;
+ break;
+ case QUESTION:
+ if (a != 0) {
+ bufnext->w_at = a;
+ (bufnext++)->w_wc = c;
+ break;
}
- /*NOTREACHED*/
-
- case '*':
- case '?':
- case '[':
- case '\\':
- ++expand;
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ bufnext->w_at = M_QUOTE;
+ (bufnext++)->w_wc = M_ONE;
break;
-
- case '/':
- if (expand)
- goto Expand;
- end = dp - *path;
- pat = (char *)sp;
+ case STAR:
+ if (a != 0) {
+ bufnext->w_at = a;
+ (bufnext++)->w_wc = c;
+ break;
+ }
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ /*
+ * collapse adjacent stars to one,
+ * to avoid exponential behavior
+ */
+ if (bufnext == patbuf ||
+ bufnext[-1].w_at != M_QUOTE ||
+ bufnext[-1].w_wc != M_ALL) {
+ bufnext->w_at = M_QUOTE;
+ (bufnext++)->w_wc = M_ALL;
+ }
break;
+ default:
+ bufnext->w_at = a;
+ (bufnext++)->w_wc = c;
+ break;
+ }
+ }
+ bufnext->w_at = 0;
+ bufnext->w_wc = EOS;
- Expand:
- /* determine directory and open it */
- (*path)[end] = '\0';
- dirp = opendir(**path == '\0' ? "." : *path);
- if (dirp == NULL) {
- if (errfn != 0 && errfn(*path, errno) != 0 ||
- flags&GLOB_ERR) {
- return (GLOB_ABORTED);
- }
- return (0);
+ if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp, errfunc))
+ != 0)
+ return (err);
+
+ /*
+ * If there was no match we are going to append the pattern
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+ * and the pattern did not contain any magic characters
+ * GLOB_NOMAGIC is there just for compatibility with csh.
+ */
+ if (pglob->gl_pathc == oldpathc) {
+ if ((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
+ !(pglob->gl_flags & GLOB_MAGCHAR)))
+ return (globextend(pattern, pglob, limitp, NULL));
+ else
+ return (GLOB_NOMATCH);
+ }
+ if (!(pglob->gl_flags & GLOB_NOSORT)) {
+ if ((pglob->gl_flags & GLOB_KEEPSTAT)) {
+ /* Keep the paths and stat info synced during sort */
+ struct glob_path_stat *path_stat;
+ int i;
+ int n = pglob->gl_pathc - oldpathc;
+ int o = pglob->gl_offs + oldpathc;
+
+ if ((path_stat = calloc(n, sizeof (*path_stat))) ==
+ NULL)
+ return (GLOB_NOSPACE);
+ for (i = 0; i < n; i++) {
+ path_stat[i].gps_path = pglob->gl_pathv[o + i];
+ path_stat[i].gps_stat = pglob->gl_statv[o + i];
+ }
+ qsort(path_stat, n, sizeof (*path_stat), compare_gps);
+ for (i = 0; i < n; i++) {
+ pglob->gl_pathv[o + i] = path_stat[i].gps_path;
+ pglob->gl_statv[o + i] = path_stat[i].gps_stat;
}
+ free(path_stat);
+ } else {
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+ pglob->gl_pathc - oldpathc, sizeof (char *),
+ compare);
+ }
+ }
+ return (0);
+}
+
+static int
+compare(const void *p, const void *q)
+{
+ return (strcmp(*(char **)p, *(char **)q));
+}
+
+static int
+compare_gps(const void *_p, const void *_q)
+{
+ const struct glob_path_stat *p = (const struct glob_path_stat *)_p;
+ const struct glob_path_stat *q = (const struct glob_path_stat *)_q;
+
+ return (strcmp(p->gps_path, q->gps_path));
+}
- /* extract pattern component */
- n = sp - pat;
- if ((cp = malloc(n)) == NULL) {
- (void) closedir(dirp);
+static int
+glob1(wcat_t *pattern, wcat_t *pattern_last, glob_t *pglob,
+ struct glob_lim *limitp, int (*errfunc)(const char *, int))
+{
+ wcat_t pathbuf[MAXPATHLEN];
+
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+ if (pattern->w_wc == EOS)
+ return (0);
+ return (glob2(pathbuf, pathbuf+MAXPATHLEN-1,
+ pathbuf, pathbuf+MAXPATHLEN-1,
+ pattern, pattern_last, pglob, limitp, errfunc));
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+static int
+glob2(wcat_t *pathbuf, wcat_t *pathbuf_last, wcat_t *pathend,
+ wcat_t *pathend_last, wcat_t *pattern, wcat_t *pattern_last,
+ glob_t *pglob, struct glob_lim *limitp, int (*errfunc)(const char *, int))
+{
+ struct stat sb;
+ wcat_t *p, *q;
+ int anymeta;
+
+ /*
+ * Loop over pattern segments until end of pattern or until
+ * segment with meta character found.
+ */
+ for (anymeta = 0; ; ) {
+ if (pattern->w_wc == EOS) { /* End of pattern? */
+ pathend->w_at = 0;
+ pathend->w_wc = EOS;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limitp->glim_stat++ >= GLOB_LIMIT_STAT) {
+ errno = 0;
+ pathend->w_at = 0;
+ (pathend++)->w_wc = SEP;
+ pathend->w_at = 0;
+ pathend->w_wc = EOS;
return (GLOB_NOSPACE);
}
- pat = memcpy(cp, pat, n);
- pat[n-1] = '\0';
- if (*--sp != '\0')
- flags |= GLOB__CHECK;
-
- /* expand path to max. expansion */
- n = dp - *path;
- *path = realloc(*path,
- strlen(*path) + NAME_MAX + strlen(sp) + 1);
- if (*path == NULL) {
- (void) closedir(dirp);
- free(pat);
+ if (g_lstat(pathbuf, &sb, pglob))
+ return (0);
+
+ if (((pglob->gl_flags & GLOB_MARK) &&
+ (pathend[-1].w_at != 0 ||
+ pathend[-1].w_wc != SEP)) &&
+ (S_ISDIR(sb.st_mode) ||
+ (S_ISLNK(sb.st_mode) &&
+ (g_stat(pathbuf, &sb, pglob) == 0) &&
+ S_ISDIR(sb.st_mode)))) {
+ if (pathend+1 > pathend_last)
+ return (GLOB_NOSPACE);
+ pathend->w_at = 0;
+ (pathend++)->w_wc = SEP;
+ pathend->w_at = 0;
+ pathend->w_wc = EOS;
+ }
+ ++pglob->gl_matchc;
+ return (globextend(pathbuf, pglob, limitp, &sb));
+ }
+
+ /* Find end of next segment, copy tentatively to pathend. */
+ q = pathend;
+ p = pattern;
+ while (p->w_wc != EOS && p->w_wc != SEP) {
+ if (ismeta(*p))
+ anymeta = 1;
+ if (q+1 > pathend_last)
return (GLOB_NOSPACE);
+ *q++ = *p++;
+ }
+
+ if (!anymeta) { /* No expansion, do next segment. */
+ pathend = q;
+ pattern = p;
+ while (pattern->w_wc == SEP) {
+ if (pathend+1 > pathend_last)
+ return (GLOB_NOSPACE);
+ *pathend++ = *pattern++;
}
- dp = (*path) + n;
-
- /* read directory and match entries */
- err = 0;
- while ((d = readdir64(dirp)) != NULL) {
- cp = d->d_name;
- if ((flags&GLOB_NOESCAPE)
- ? fnmatch(pat, cp, FNM_PERIOD|FNM_NOESCAPE)
- : fnmatch(pat, cp, FNM_PERIOD))
- continue;
-
- n = strlen(cp);
- (void) memcpy((*path) + end, cp, n);
- m = dp - *path;
- err = globit(end+n, sp, gp, flags, errfn, path);
- dp = (*path) + m; /* globit can move path */
- if (err != 0)
- break;
+ } else {
+ /* Need expansion, recurse. */
+ return (glob3(pathbuf, pathbuf_last, pathend,
+ pathend_last, pattern, p, pattern_last,
+ pglob, limitp, errfunc));
+ }
+ }
+ /* NOTREACHED */
+}
+
+static int
+glob3(wcat_t *pathbuf, wcat_t *pathbuf_last, wcat_t *pathend,
+ wcat_t *pathend_last, wcat_t *pattern, wcat_t *restpattern,
+ wcat_t *restpattern_last, glob_t *pglob, struct glob_lim *limitp,
+ int (*errfunc)(const char *, int))
+{
+ struct dirent *dp;
+ DIR *dirp;
+ int err;
+ char buf[MAXPATHLEN];
+
+ /*
+ * The readdirfunc declaration can't be prototyped, because it is
+ * assigned, below, to two functions which are prototyped in glob.h
+ * and dirent.h as taking pointers to differently typed opaque
+ * structures.
+ */
+ struct dirent *(*readdirfunc)(void *);
+
+ if (pathend > pathend_last)
+ return (GLOB_NOSPACE);
+ pathend->w_at = 0;
+ pathend->w_wc = EOS;
+ errno = 0;
+
+ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+ /* TODO: don't call for ENOENT or ENOTDIR? */
+ if (errfunc) {
+ if (g_Ctoc(pathbuf, buf, sizeof (buf)))
+ return (GLOB_ABORTED);
+ if (errfunc(buf, errno) ||
+ pglob->gl_flags & GLOB_ERR)
+ return (GLOB_ABORTED);
+ }
+ return (0);
+ }
+
+ err = 0;
+
+ /* Search directory for matching names. */
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ readdirfunc = pglob->gl_readdir;
+ else
+ readdirfunc = (struct dirent *(*)(void *))readdir;
+ while ((dp = (*readdirfunc)(dirp))) {
+ char *sc;
+ wcat_t *dc;
+ int n;
+ int lensc;
+ wchar_t w;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) {
+ errno = 0;
+ pathend->w_at = 0;
+ (pathend++)->w_wc = SEP;
+ pathend->w_at = 0;
+ pathend->w_wc = EOS;
+ err = GLOB_NOSPACE;
+ break;
+ }
+
+ /* Initial DOT must be matched literally. */
+ if (dp->d_name[0] == DOT && pattern->w_wc != DOT)
+ continue;
+ dc = pathend;
+ sc = dp->d_name;
+ lensc = strlen(sc) + 1;
+ while (dc < pathend_last) {
+ if ((n = mbtowc(&w, sc, lensc)) <= 0) {
+ sc += 1;
+ lensc -= 1;
+ dc->w_at = 0;
+ dc->w_wc = EOS;
+ } else {
+ sc += n;
+ lensc -= n;
+ dc->w_at = 0;
+ dc->w_wc = w;
}
+ dc++;
+ if (n <= 0)
+ break;
+ }
+ if (dc >= pathend_last) {
+ dc->w_at = 0;
+ dc->w_wc = EOS;
+ err = GLOB_NOSPACE;
+ break;
+ }
+ if (n < 0) {
+ err = GLOB_NOMATCH;
+ break;
+ }
- (void) closedir(dirp);
- free(pat);
- return (err);
+ if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) {
+ pathend->w_at = 0;
+ pathend->w_wc = EOS;
+ continue;
}
- /* NOTREACHED */
+ err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
+ restpattern, restpattern_last, pglob, limitp,
+ errfunc);
+ if (err)
+ break;
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ (*pglob->gl_closedir)(dirp);
+ else
+ (void) closedir(dirp);
+ return (err);
}
+
/*
- * Comparison routine for two name arguments, called by qsort.
+ * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
+ * add the new item, and update gl_pathc. Avoids excessive reallocation
+ * by doubling the number of elements each time. Uses gl_pathn to contain
+ * the number.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
*/
-int
-pstrcmp(const void *npp1, const void *npp2)
+static int
+globextend(const wcat_t *path, glob_t *pglob, struct glob_lim *limitp,
+ struct stat *sb)
{
- return (strcoll(*(char **)npp1, *(char **)npp2));
+ char **pathv;
+ ssize_t i;
+ size_t allocn, newn, len;
+ char *copy = NULL;
+ const wcat_t *p;
+ struct stat **statv;
+ char junk[MB_LEN_MAX];
+ int n;
+
+ allocn = pglob->gl_pathn;
+ newn = 2 + pglob->gl_pathc + pglob->gl_offs;
+
+ if (newn <= allocn) {
+ pathv = pglob->gl_pathv;
+ if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0)
+ statv = pglob->gl_statv;
+ } else {
+ if (allocn == 0)
+ allocn = pglob->gl_offs + INITIAL;
+ allocn *= 2;
+ if (pglob->gl_offs >= INT_MAX ||
+ pglob->gl_pathc >= INT_MAX ||
+ allocn >= INT_MAX ||
+ SIZE_MAX / sizeof (*pathv) <= allocn ||
+ SIZE_MAX / sizeof (*statv) <= allocn) {
+ nospace:
+ for (i = pglob->gl_offs; i < (ssize_t)(newn - 2);
+ i++) {
+ if (pglob->gl_pathv && pglob->gl_pathv[i])
+ free(pglob->gl_pathv[i]);
+ if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
+ pglob->gl_statv && pglob->gl_statv[i])
+ free(pglob->gl_statv[i]);
+ }
+ if (pglob->gl_pathv) {
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+ if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
+ pglob->gl_statv) {
+ free(pglob->gl_statv);
+ pglob->gl_statv = NULL;
+ }
+ return (GLOB_NOSPACE);
+ }
+ limitp->glim_malloc += allocn * sizeof (*pathv);
+ pathv = realloc(pglob->gl_pathv, allocn * sizeof (*pathv));
+ if (pathv == NULL)
+ goto nospace;
+ if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) {
+ limitp->glim_malloc += allocn * sizeof (*statv);
+ statv = realloc(pglob->gl_statv,
+ allocn * sizeof (*statv));
+ if (statv == NULL)
+ goto nospace;
+ }
+ }
+ pglob->gl_pathn = allocn;
+
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs; --i >= 0; )
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) {
+ if (pglob->gl_statv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ statv += pglob->gl_offs;
+ for (i = pglob->gl_offs; --i >= 0; )
+ *--statv = NULL;
+ }
+ pglob->gl_statv = statv;
+ if (sb == NULL)
+ statv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+ else {
+ limitp->glim_malloc += sizeof (**statv);
+ if ((statv[pglob->gl_offs + pglob->gl_pathc] =
+ malloc(sizeof (**statv))) == NULL)
+ goto copy_error;
+ (void) memcpy(statv[pglob->gl_offs + pglob->gl_pathc],
+ sb, sizeof (*sb));
+ }
+ statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL;
+ }
+
+ len = MB_LEN_MAX;
+ p = path;
+ while ((n = wctomb(junk, p->w_wc)) > 0) {
+ len += n;
+ if ((p++)->w_wc == EOS)
+ break;
+ }
+ if (n < 0)
+ return (GLOB_NOMATCH);
+
+ limitp->glim_malloc += len;
+ if ((copy = malloc(len)) != NULL) {
+ if (g_Ctoc(path, copy, len)) {
+ free(copy);
+ return (GLOB_NOSPACE);
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limitp->glim_malloc >= GLOB_LIMIT_MALLOC) {
+ errno = 0;
+ return (GLOB_NOSPACE);
+ }
+ copy_error:
+ return (copy == NULL ? GLOB_NOSPACE : 0);
}
+
/*
- * Add a new matched filename to the glob_t structure, increasing the
- * size of that array, as required.
+ * pattern matching function for filenames. Each occurrence of the *
+ * pattern causes a recursion level.
*/
-int
-append(glob_t *gp, const char *str)
+static int
+match(wcat_t *name, wcat_t *pat, wcat_t *patend, int recur)
{
- char *cp;
+ int ok, negate_range;
+ wcat_t c, k;
- if ((cp = malloc(strlen(str)+1)) == NULL)
- return (GLOB_NOSPACE);
- gp->gl_pathp[gp->gl_pathc++] = strcpy(cp, str);
+ if (recur-- == 0)
+ return (1);
- if ((gp->gl_pathc + gp->gl_offs) >= gp->gl_pathn) {
- gp->gl_pathn *= 2;
- gp->gl_pathv = (char **)realloc((void *)gp->gl_pathv,
- gp->gl_pathn * sizeof (char *));
- if (gp->gl_pathv == NULLCPP)
- return (GLOB_NOSPACE);
- gp->gl_pathp = gp->gl_pathv + gp->gl_offs;
+ while (pat < patend) {
+ c = *pat++;
+ switch (c.w_wc) {
+ case M_ALL:
+ if (c.w_at != M_QUOTE) {
+ k = *name++;
+ if (k.w_at != c.w_at || k.w_wc != c.w_wc)
+ return (0);
+ break;
+ }
+ while (pat < patend && pat->w_at == M_QUOTE &&
+ pat->w_wc == M_ALL)
+ pat++; /* eat consecutive '*' */
+ if (pat == patend)
+ return (1);
+ do {
+ if (match(name, pat, patend, recur))
+ return (1);
+ } while ((name++)->w_wc != EOS);
+ return (0);
+ case M_ONE:
+ if (c.w_at != M_QUOTE) {
+ k = *name++;
+ if (k.w_at != c.w_at || k.w_wc != c.w_wc)
+ return (0);
+ break;
+ }
+ if ((name++)->w_wc == EOS)
+ return (0);
+ break;
+ case M_SET:
+ if (c.w_at != M_QUOTE) {
+ k = *name++;
+ if (k.w_at != c.w_at || k.w_wc != c.w_wc)
+ return (0);
+ break;
+ }
+ ok = 0;
+ if ((k = *name++).w_wc == EOS)
+ return (0);
+ if ((negate_range = (pat->w_at == M_QUOTE &&
+ pat->w_wc == M_NOT)) != 0)
+ ++pat;
+ while (((c = *pat++).w_at != M_QUOTE) ||
+ c.w_wc != M_END) {
+ if (c.w_at == M_QUOTE && c.w_wc == M_CLASS) {
+ wcat_t cc;
+
+ cc.w_at = pat->w_at;
+ cc.w_wc = pat->w_wc;
+ if (iswctype(k.w_wc, cc.w_wc))
+ ok = 1;
+ ++pat;
+ }
+ if (pat->w_at == M_QUOTE &&
+ pat->w_wc == M_RNG) {
+ if (c.w_wc <= k.w_wc &&
+ k.w_wc <= pat[1].w_wc)
+ ok = 1;
+ pat += 2;
+ } else if (c.w_wc == k.w_wc)
+ ok = 1;
+ }
+ if (ok == negate_range)
+ return (0);
+ break;
+ default:
+ k = *name++;
+ if (k.w_at != c.w_at || k.w_wc != c.w_wc)
+ return (0);
+ break;
+ }
}
- return (0);
+ return (name->w_wc == EOS);
+}
+
+/*
+ * Extended globfree() function, selected by #pragma redefine_extname
+ * in glob.h with the external name _globfree_ext() .
+ */
+void
+_globfree_ext(glob_t *pglob)
+{
+ int i;
+ char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ free(*pp);
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+ if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
+ pglob->gl_statv != NULL) {
+ for (i = 0; i < pglob->gl_pathc; i++) {
+ if (pglob->gl_statv[i] != NULL)
+ free(pglob->gl_statv[i]);
+ }
+ free(pglob->gl_statv);
+ pglob->gl_statv = NULL;
+ }
+}
+
+static DIR *
+g_opendir(wcat_t *str, glob_t *pglob)
+{
+ char buf[MAXPATHLEN];
+
+ if (str->w_wc == EOS)
+ (void) strlcpy(buf, ".", sizeof (buf));
+ else {
+ if (g_Ctoc(str, buf, sizeof (buf)))
+ return (NULL);
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return ((*pglob->gl_opendir)(buf));
+
+ return (opendir(buf));
+}
+
+static int
+g_lstat(wcat_t *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[MAXPATHLEN];
+
+ if (g_Ctoc(fn, buf, sizeof (buf)))
+ return (-1);
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return ((*pglob->gl_lstat)(buf, sb));
+ return (lstat(buf, sb));
}
+
+static int
+g_stat(wcat_t *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[MAXPATHLEN];
+
+ if (g_Ctoc(fn, buf, sizeof (buf)))
+ return (-1);
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return ((*pglob->gl_stat)(buf, sb));
+ return (stat(buf, sb));
+}
+
+static wcat_t *
+g_strchr(const wcat_t *str, wchar_t ch)
+{
+ do {
+ if (str->w_at == 0 && str->w_wc == ch)
+ return ((wcat_t *)str);
+ } while ((str++)->w_wc != EOS);
+ return (NULL);
+}
+
+static int
+g_Ctoc(const wcat_t *str, char *buf, uint_t len)
+{
+ int n;
+ wchar_t w;
+
+ while (len >= MB_LEN_MAX) {
+ w = (str++)->w_wc;
+ if ((n = wctomb(buf, w)) > 0) {
+ len -= n;
+ buf += n;
+ }
+ if (n < 0)
+ break;
+ if (w == EOS)
+ return (0);
+ }
+ return (1);
+}
+
+/* glob() function with legacy glob structure */
+int
+old_glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
+ old_glob_t *pglob)
+{
+
+ glob_t gl;
+ int rv;
+
+ flags &= GLOB_POSIX;
+
+ (void) memset(&gl, 0, sizeof (gl));
+
+ /*
+ * Copy all the members, old to new. There's
+ * really no point in micro-optimizing the copying.
+ * Other members are set to zero.
+ */
+ gl.gl_pathc = pglob->gl_pathc;
+ gl.gl_pathv = pglob->gl_pathv;
+ gl.gl_offs = pglob->gl_offs;
+ gl.gl_pathp = pglob->gl_pathp;
+ gl.gl_pathn = pglob->gl_pathn;
+
+ rv = _glob_ext(pattern, flags, errfunc, &gl);
+
+ /*
+ * Copy all the members, new to old. There's
+ * really no point in micro-optimizing the copying.
+ */
+ pglob->gl_pathc = gl.gl_pathc;
+ pglob->gl_pathv = gl.gl_pathv;
+ pglob->gl_offs = gl.gl_offs;
+ pglob->gl_pathp = gl.gl_pathp;
+ pglob->gl_pathn = gl.gl_pathn;
+
+ return (rv);
+}
+
+/* globfree() function with legacy glob structure */
+void
+old_globfree(old_glob_t *pglob)
+{
+ glob_t gl;
+
+ (void) memset(&gl, 0, sizeof (gl));
+
+ /*
+ * Copy all the members, old to new. There's
+ * really no point in micro-optimizing the copying.
+ * Other members are set to zero.
+ */
+ gl.gl_pathc = pglob->gl_pathc;
+ gl.gl_pathv = pglob->gl_pathv;
+ gl.gl_offs = pglob->gl_offs;
+ gl.gl_pathp = pglob->gl_pathp;
+ gl.gl_pathn = pglob->gl_pathn;
+
+ _globfree_ext(&gl);
+
+ /*
+ * Copy all the members, new to old. There's
+ * really no point in micro-optimizing the copying.
+ */
+ pglob->gl_pathc = gl.gl_pathc;
+ pglob->gl_pathv = gl.gl_pathv;
+ pglob->gl_offs = gl.gl_offs;
+ pglob->gl_pathp = gl.gl_pathp;
+ pglob->gl_pathn = gl.gl_pathn;
+
+}
+
+/* End */
diff --git a/usr/src/man/man3c/glob.3c b/usr/src/man/man3c/glob.3c
index 968593d341..b0559e1137 100644
--- a/usr/src/man/man3c/glob.3c
+++ b/usr/src/man/man3c/glob.3c
@@ -1,8 +1,42 @@
'\" te
-.\" Copyright (c) 1992, X/Open Company Limited. All Rights Reserved. Portions Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright (c) 1992, X/Open Company Limited. All Rights Reserved.
+.\" Portions Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved.
+.\" Portions Copyright (c) 2013, Gary Mills
.\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at
.\" http://www.opengroup.org/bookstore/.
.\" The Institute of Electrical and Electronics Engineers and The Open Group, have given us permission to reprint portions of their documentation. In the following statement, the phrase "this text" refers to portions of the system documentation. Portions of this text are reprinted and reproduced in electronic form in the Sun OS Reference Manual, from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- Portable Operating System Interface (POSIX), The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any discrepancy between these versions and the original IEEE and The Open Group Standard, the original IEEE and The Open Group Standard is the referee document. The original Standard can be obtained online at http://www.opengroup.org/unix/online.html.
+.\"
+.\" $OpenBSD: glob.3,v 1.30 2012/01/20 07:09:42 tedu Exp $
+.\"
+.\" Copyright (c) 1989, 1991, 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.
+.\" 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.
+.\"
.\" This notice shall appear on any product containing this material.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
@@ -58,12 +92,12 @@ includes at least the following members:
.sp
.in +2
.nf
-size_t gl_pathc; /* count of paths matched by */
+size_t gl_pathc; /* Total count of paths matched by */
/* pattern */
-char **gl_pathv; /* pointer to list of matched */
- /* path names */
-size_t gl_offs; /* slots to reserve at beginning */
- /* of gl_pathv */
+char **gl_pathv; /* List of matched path names */
+size_t gl_offs; /* # of slots reserved in gl_pathv */
+int gl_matchc; /* Count of paths matching pattern. */
+int gl_flags; /* Copy of flags parameter to glob. */
.fi
.in -2
@@ -164,6 +198,116 @@ path names returned is unspecified.
.RE
.sp
+.ne 2
+.na
+\fB\fBGLOB_ALTDIRFUNC\fR\fR
+.ad
+.RS 17n
+The following additional fields in the \fIpglob\fR structure
+have been initialized with alternate functions for
+\fBglob()\fR to use to open, read, and close directories and
+to get stat information on names found in those directories:
+.sp
+.nf
+void *(*gl_opendir)(const char *);
+struct dirent *(*gl_readdir)(void *);
+void (*gl_closedir)(void *);
+int (*gl_lstat)(const char *, struct stat *);
+int (*gl_stat)(const char *, struct stat *);
+.fi
+.sp
+This extension is provided to allow programs such as
+\fBufsrestore\fR(1M) to provide globbing from directories stored
+on tape.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBGLOB_BRACE\fR\fR
+.ad
+.RS 17n
+Pre-process the pattern string to expand `{pat,pat,...}'
+strings like \fBcsh\fR(1). The pattern `{}' is left unexpanded
+for historical reasons. (\fBcsh\fR(1) does the same thing
+to ease typing of \fBfind\fR(1) patterns.)
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBGLOB_MAGCHAR\fR\fR
+.ad
+.RS 17n
+Set by the \fBglob()\fR function if the pattern included globbing
+characters. See the description of the usage of
+the \fBgl_matchc\fR structure member for more details.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBGLOB_NOMAGIC\fR\fR
+.ad
+.RS 17n
+Is the same as \fBGLOB_NOCHECK\fR but it only appends the
+pattern if it does not contain any of the special characters
+`*', `?', or `['. \fBGLOB_NOMAGIC\fR is provided to
+simplify implementing the historic \fBcsh\fR(1) globbing behavior
+and should probably not be used anywhere else.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBGLOB_QUOTE\fR\fR
+.ad
+.RS 17n
+This option has no effect and is included for backwards
+compatibility with older sources.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBGLOB_TILDE\fR\fR
+.ad
+.RS 17n
+Expand patterns that start with `~' to user name home
+directories.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBGLOB_LIMIT\fR\fR
+.ad
+.RS 17n
+Limit the amount of memory used by matches to \fIARG_MAX\fR.
+This option should be set for programs that can be coerced
+to a denial of service attack via patterns that
+expand to a very large number of matches, such as a long
+string of `*/../*/..'.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBGLOB_KEEPSTAT\fR\fR
+.ad
+.RS 17n
+Retain a copy of the \fBstat\fR(2) information retrieved for
+matching paths in the gl_statv array:
+.sp
+.nf
+struct stat **gl_statv;
+.fi
+.sp
+This option may be used to avoid \fBlstat\fR(2) lookups in
+cases where they are expensive.
+.RE
+
+.sp
.LP
The \fBGLOB_APPEND\fR flag can be used to append a new set of path names to
those found in a previous call to \fBglob()\fR. The following rules apply when
@@ -237,74 +381,122 @@ set by the \fBopendir\fR(3C), \fBreaddir\fR(3C) or \fBstat\fR(2) functions.
(Other values may be used to report other errors not explicitly documented for
those functions.)
.RE
+
.sp
.LP
-The following constants are defined as error return values for \fBglob()\fR:
+If \fB(\fR\fI*errfunc\fR\fB)\fR is called and returns non-zero, or if the
+\fBGLOB_ERR\fR flag is set in \fIflags\fR, \fBglob()\fR stops the scan and
+returns \fBGLOB_ABORTED\fR after setting \fIgl_pathc\fR and \fIgl_pathv\fR in
+\fIpglob\fR to reflect the paths already scanned. If \fBGLOB_ERR\fR is not set
+and either \fIerrfunc\fR is a \fINULL\fR pointer or
+\fB(\fR\fI*errfunc\fR\fB)\fR returns 0, the error is ignored.
+.SH RETURN VALUES
+.sp
+.LP
+On successful completion, \fBglob()\fR returns zero.
+In addition the fields of pglob contain the values described below:
+
.sp
.ne 2
.na
-\fB\fBGLOB_ABORTED\fR\fR
+\fB\fBgl_pathc\fR\fR
.ad
.RS 16n
-The scan was stopped because \fBGLOB_ERR\fR was set or
-\fB(\fR\fI*errfunc\fR\fB)\fR returned non-zero.
+Contains the total number of matched pathnames so far.
+This includes other matches from previous invocations of
+\fBglob()\fR if \fBGLOB_APPEND\fR was specified.
.RE
.sp
.ne 2
.na
-\fB\fBGLOB_NOMATCH\fR\fR
+\fB\fBgl_matchc\fR\fR
.ad
.RS 16n
-The pattern does not match any existing path name, and \fBGLOB_NOCHECK\fR was
-not set in flags.
+Contains the number of matched pathnames in the current
+invocation of \fBglob()\fR.
.RE
.sp
.ne 2
.na
-\fB\fBGLOG_NOSPACE\fR\fR
+\fB\fBgl_flags\fR\fR
.ad
.RS 16n
-An attempt to allocate memory failed.
+Contains a copy of the flags parameter with the bit
+\fBGLOB_MAGCHAR\fR set if pattern contained any of the special
+characters `*', `?', or `[', cleared if not.
.RE
.sp
-.LP
-If \fB(\fR\fI*errfunc\fR\fB)\fR is called and returns non-zero, or if the
-\fBGLOB_ERR\fR flag is set in \fIflags\fR, \fBglob()\fR stops the scan and
-returns \fBGLOB_ABORTED\fR after setting \fIgl_pathc\fR and \fIgl_pathv\fR in
-\fIpglob\fR to reflect the paths already scanned. If \fBGLOB_ERR\fR is not set
-and either \fIerrfunc\fR is a \fINULL\fR pointer or
-\fB(\fR\fI*errfunc\fR\fB)\fR returns 0, the error is ignored.
-.SH RETURN VALUES
+.ne 2
+.na
+\fB\fBgl_pathv\fR\fR
+.ad
+.RS 16n
+Contains a pointer to a null-terminated list of matched
+pathnames. However, if \fBgl_pathc\fR is zero, the contents of
+\fBgl_pathv\fR are undefined.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBgl_statv\fR\fR
+.ad
+.RS 16n
+If the \fBGLOB_KEEPSTAT\fR flag was set, \fBgl_statv\fR contains a
+pointer to a null-terminated list of matched \fBstat\fR(2)
+objects corresponding to the paths in \fBgl_pathc\fR.
+.RE
+
.sp
.LP
-The following values are returned by \fBglob()\fR:
+If \fBglob()\fR terminates due to an error, it sets \fBerrno\fR and
+returns one of the following non-zero constants. defined in <\fBglob.h\fR>:
+
+.sp
+.ne 2
+.na
+\fB\fBGLOB_ABORTED\fR\fR
+.ad
+.RS 16n
+The scan was stopped because \fBGLOB_ERR\fR was set or
+\fB(\fR\fI*errfunc\fR\fB)\fR returned non-zero.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBGLOB_NOMATCH\fR\fR
+.ad
+.RS 16n
+The pattern does not match any existing path name, and \fBGLOB_NOCHECK\fR was
+not set in flags.
+.RE
+
.sp
.ne 2
.na
-\fB\fB0\fR\fR
+\fB\fBGLOB_NOSPACE\fR\fR
.ad
-.RS 12n
-Successful completion. The argument \fIpglob\(mi>\fR\fBgl_pathc\fR returns the
-number of matched path names and the argument \fIpglob\(mi>\fR\fBgl_pathv\fR
-contains a pointer to a null-terminated list of matched and sorted path names.
-However, if \fIpglob\(mi>\fR\fBgl_pathc\fR is 0, the content of
-\fIpglob\(mi>\fR\fBgl_pathv\fR is undefined.
+.RS 16n
+An attempt to allocate memory failed.
.RE
.sp
.ne 2
.na
-\fB\fBnon-zero\fR\fR
+\fB\fBGLOB_NOSYS\fR\fR
.ad
-.RS 12n
-An error has occurred. Non-zero constants are defined in <\fBglob.h\fR>. The
-arguments \fIpglob\(mi>\fR\fBgl_pathc\fR and \fIpglob\(mi>\fR\fBgl_pathv\fR are
-still set as defined above.
+.RS 16n
+The requested function is not supported by this version of
+\fBglob()\fR.
.RE
+.LP
+The arguments \fIpglob\(mi>\fR\fBgl_pathc\fR and \fIpglob\(mi>\fR\fBgl_pathv\fR are still set as
+specified above.
.sp
.LP
The \fBglobfree()\fR function returns no value.
diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf
index 4b137334cc..8af4c375f6 100644
--- a/usr/src/pkg/manifests/system-test-zfstest.mf
+++ b/usr/src/pkg/manifests/system-test-zfstest.mf
@@ -1405,3 +1405,4 @@ license cr_Sun license=cr_Sun
license lic_CDDL license=lic_CDDL
depend fmri=system/file-system/zfs/tests type=require
depend fmri=system/test/testrunner type=require
+depend fmri=system/xopen/xcu4 type=require
diff --git a/usr/src/test/zfs-tests/cmd/chg_usr_exec/chg_usr_exec.c b/usr/src/test/zfs-tests/cmd/chg_usr_exec/chg_usr_exec.c
index af09d21ebb..55ea1e7967 100644
--- a/usr/src/test/zfs-tests/cmd/chg_usr_exec/chg_usr_exec.c
+++ b/usr/src/test/zfs-tests/cmd/chg_usr_exec/chg_usr_exec.c
@@ -31,7 +31,7 @@
#include <errno.h>
#include <pwd.h>
-/* extern int errno = 0; */
+#define EXECSHELL "/usr/xpg4/bin/sh"
int
main(int argc, char *argv[])
@@ -68,8 +68,8 @@ main(int argc, char *argv[])
return (errno);
}
- if (execl("/usr/xpg4/bin/sh", "sh", "-c", cmds, (char *)0) != 0) {
- perror("execl");
+ if (execl(EXECSHELL, "sh", "-c", cmds, (char *)NULL) != 0) {
+ perror("execl: " EXECSHELL);
return (errno);
}
diff --git a/usr/src/test/zfs-tests/tests/functional/acl/acl.cfg b/usr/src/test/zfs-tests/tests/functional/acl/acl.cfg
index 58b6f5d5d0..fbebe38841 100644
--- a/usr/src/test/zfs-tests/tests/functional/acl/acl.cfg
+++ b/usr/src/test/zfs-tests/tests/functional/acl/acl.cfg
@@ -31,8 +31,8 @@ export TESTFILE=testfile$$
export TESTFILE0=testfile0.$$
export TESTFILE2=testfile2.$$
-# Define super user 'admin'
-export ZFS_ACL_ADMIN=admin
+# Define super user 'zfstest'
+export ZFS_ACL_ADMIN=zfstest
export ZFS_ACL_STAFF_GROUP=zfsgrp
export ZFS_ACL_STAFF1=staff1
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
index 72dd0904ef..0cd3b4f2ab 100644
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
@@ -32,4 +32,6 @@
typeset -a properties=("size" "capacity" "altroot" "health" "guid" "version"
"bootfs" "delegation" "autoreplace" "cachefile" "dedupditto" "dedupratio"
"free" "allocated" "readonly" "comment" "expandsize" "freeing" "failmode"
- "listsnapshots" "autoexpand" "feature@async_destroy" "feature@empty_bpobj")
+ "listsnapshots" "autoexpand" "feature@async_destroy" "feature@empty_bpobj"
+ "feature@lz4_compress" "feature@multi_vdev_crash_dump"
+ "feature@spacemap_histogram" "feature@extensible_dataset")
diff --git a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c
index ed7c474631..e5c6c6ee69 100644
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c
@@ -871,8 +871,8 @@ mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
"prop update failed");
return (DDI_FAILURE);
}
- mptsas_smhba_set_phy_props(mpt,
- iport, dip, numphys, &attached_devhdl);
+ mptsas_smhba_set_all_phy_props(mpt, dip, numphys, phy_mask,
+ &attached_devhdl);
mutex_enter(&mpt->m_mutex);
page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
@@ -5953,9 +5953,14 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
return;
}
mutex_exit(&mpt->m_mutex);
- mptsas_smhba_set_phy_props(mpt,
- ddi_get_name_addr(parent), parent,
- 1, &attached_devhdl);
+
+ /*
+ * topo_node->un.physport is really the PHY#
+ * for direct attached devices
+ */
+ mptsas_smhba_set_one_phy_props(mpt, parent,
+ topo_node->un.physport, &attached_devhdl);
+
if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
MPTSAS_VIRTUAL_PORT, 0) !=
DDI_PROP_SUCCESS) {
@@ -14899,8 +14904,8 @@ mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
}
mutex_exit(&mpt->m_mutex);
- mptsas_smhba_set_phy_props(mpt, iport, pdip,
- numphys, &attached_devhdl);
+ mptsas_smhba_set_all_phy_props(mpt, pdip, numphys, phy_mask,
+ &attached_devhdl);
if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
MPTSAS_NUM_PHYS, numphys) !=
diff --git a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_smhba.c b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_smhba.c
index 91443214bf..afeb334a0f 100644
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_smhba.c
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_smhba.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
* This file contains SM-HBA support for MPT SAS driver
@@ -59,6 +60,11 @@
*/
extern char *mptsas_driver_rev;
+static void mptsas_smhba_create_phy_props(nvlist_t **, smhba_info_t *, uint8_t,
+ uint16_t *);
+static void mptsas_smhba_update_phy_props(mptsas_t *, dev_info_t *, nvlist_t **,
+ uint8_t);
+
static void
mptsas_smhba_add_hba_prop(mptsas_t *mpt, data_type_t dt,
char *prop_name, void *prop_val);
@@ -116,79 +122,48 @@ mptsas_smhba_show_phy_info(mptsas_t *mpt)
}
}
-void
-mptsas_smhba_set_phy_props(mptsas_t *mpt, char *iport, dev_info_t *dip,
- uint8_t phy_nums, uint16_t *attached_devhdl)
+static void
+mptsas_smhba_create_phy_props(nvlist_t **phy_props, smhba_info_t *pSmhba,
+ uint8_t phy_id, uint16_t *attached_devhdl)
+{
+ (void) nvlist_alloc(phy_props, NV_UNIQUE_NAME, KM_SLEEP);
+ (void) nvlist_add_uint8(*phy_props, SAS_PHY_ID, phy_id);
+ (void) nvlist_add_uint8(*phy_props, "phyState",
+ (pSmhba->negotiated_link_rate & 0x0f));
+ (void) nvlist_add_int8(*phy_props, SAS_NEG_LINK_RATE,
+ (pSmhba->negotiated_link_rate & 0x0f));
+ (void) nvlist_add_int8(*phy_props, SAS_PROG_MIN_LINK_RATE,
+ (pSmhba->programmed_link_rate & 0x0f));
+ (void) nvlist_add_int8(*phy_props, SAS_HW_MIN_LINK_RATE,
+ (pSmhba->hw_link_rate & 0x0f));
+ (void) nvlist_add_int8(*phy_props, SAS_PROG_MAX_LINK_RATE,
+ ((pSmhba->programmed_link_rate & 0xf0) >> 4));
+ (void) nvlist_add_int8(*phy_props, SAS_HW_MAX_LINK_RATE,
+ ((pSmhba->hw_link_rate & 0xf0) >> 4));
+
+ if (pSmhba->attached_devhdl && (attached_devhdl != NULL))
+ *attached_devhdl = pSmhba->attached_devhdl;
+}
+
+static void
+mptsas_smhba_update_phy_props(mptsas_t *mpt, dev_info_t *dip,
+ nvlist_t **phy_props, uint8_t phy_nums)
{
- int i;
- int j = 0;
int rval;
size_t packed_size;
char *packed_data = NULL;
- char phymask[MPTSAS_MAX_PHYS];
- nvlist_t **phy_props;
nvlist_t *nvl;
- smhba_info_t *pSmhba = NULL;
- if (phy_nums == 0) {
- return;
- }
- if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
+ if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) != 0) {
mptsas_log(mpt, CE_WARN, "%s: nvlist_alloc() failed", __func__);
- }
-
- phy_props = kmem_zalloc(sizeof (nvlist_t *) * phy_nums,
- KM_SLEEP);
-
- for (i = 0; i < mpt->m_num_phys; i++) {
-
- bzero(phymask, sizeof (phymask));
- (void) sprintf(phymask, "%x", mpt->m_phy_info[i].phy_mask);
- if (strcmp(phymask, iport) == 0) {
- pSmhba = &mpt->m_phy_info[i].smhba_info;
- (void) nvlist_alloc(&phy_props[j], NV_UNIQUE_NAME, 0);
- (void) nvlist_add_uint8(phy_props[j], SAS_PHY_ID, i);
- (void) nvlist_add_uint8(phy_props[j],
- "phyState",
- (pSmhba->negotiated_link_rate
- & 0x0f));
- (void) nvlist_add_int8(phy_props[j],
- SAS_NEG_LINK_RATE,
- (pSmhba->negotiated_link_rate
- & 0x0f));
- (void) nvlist_add_int8(phy_props[j],
- SAS_PROG_MIN_LINK_RATE,
- (pSmhba->programmed_link_rate
- & 0x0f));
- (void) nvlist_add_int8(phy_props[j],
- SAS_HW_MIN_LINK_RATE,
- (pSmhba->hw_link_rate
- & 0x0f));
- (void) nvlist_add_int8(phy_props[j],
- SAS_PROG_MAX_LINK_RATE,
- ((pSmhba->programmed_link_rate
- & 0xf0) >> 4));
- (void) nvlist_add_int8(phy_props[j],
- SAS_HW_MAX_LINK_RATE,
- ((pSmhba->hw_link_rate
- & 0xf0) >> 4));
-
- j++;
-
- if (pSmhba->attached_devhdl &&
- (attached_devhdl != NULL)) {
- *attached_devhdl =
- pSmhba->attached_devhdl;
- }
- }
+ return;
}
rval = nvlist_add_nvlist_array(nvl, SAS_PHY_INFO_NVL, phy_props,
phy_nums);
if (rval) {
mptsas_log(mpt, CE_WARN,
- " nv list array add failed, return value %d.",
- rval);
+ " nv list array add failed, return value %d.", rval);
goto exit;
}
(void) nvlist_size(nvl, &packed_size, NV_ENCODE_NATIVE);
@@ -200,17 +175,54 @@ mptsas_smhba_set_phy_props(mptsas_t *mpt, char *iport, dev_info_t *dip,
SAS_PHY_INFO, (uchar_t *)packed_data, packed_size);
exit:
- for (i = 0; i < phy_nums && phy_props[i] != NULL; i++) {
- nvlist_free(phy_props[i]);
- }
nvlist_free(nvl);
- kmem_free(phy_props, sizeof (nvlist_t *) * phy_nums);
if (packed_data != NULL) {
kmem_free(packed_data, packed_size);
}
}
+void
+mptsas_smhba_set_one_phy_props(mptsas_t *mpt, dev_info_t *dip, uint8_t phy_id,
+ uint16_t *attached_devhdl)
+{
+ nvlist_t *phy_props;
+
+ ASSERT(phy_id < mpt->m_num_phys);
+
+ mptsas_smhba_create_phy_props(&phy_props,
+ &mpt->m_phy_info[phy_id].smhba_info, phy_id, attached_devhdl);
+
+ mptsas_smhba_update_phy_props(mpt, dip, &phy_props, 1);
+
+ nvlist_free(phy_props);
+}
+
+void
+mptsas_smhba_set_all_phy_props(mptsas_t *mpt, dev_info_t *dip, uint8_t phy_nums,
+ mptsas_phymask_t phy_mask, uint16_t *attached_devhdl)
+{
+ int i, j;
+ nvlist_t **phy_props;
+
+ if (phy_nums == 0)
+ return;
+
+ phy_props = kmem_zalloc(sizeof (nvlist_t *) * phy_nums, KM_SLEEP);
+
+ for (i = 0, j = 0; i < mpt->m_num_phys && j < phy_nums; i++)
+ if (phy_mask == mpt->m_phy_info[i].phy_mask)
+ mptsas_smhba_create_phy_props(&phy_props[j++],
+ &mpt->m_phy_info[i].smhba_info, i, attached_devhdl);
+
+ mptsas_smhba_update_phy_props(mpt, dip, phy_props, j);
+
+ for (i = 0; i < j && phy_props[i] != NULL; i++)
+ nvlist_free(phy_props[i]);
+
+ kmem_free(phy_props, sizeof (nvlist_t *) * phy_nums);
+}
+
/*
* Called with PHY lock held on phyp
*/
diff --git a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_smhba.h b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_smhba.h
index 5969ea63f1..adad051f38 100644
--- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_smhba.h
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_smhba.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -63,8 +64,10 @@ extern "C" {
*/
int mptsas_smhba_setup(mptsas_t *);
void mptsas_smhba_show_phy_info(mptsas_t *);
-void mptsas_smhba_set_phy_props(mptsas_t *mpt, char *iport, dev_info_t *dip,
- uint8_t phy_nums, uint16_t *attached_devhdl);
+void mptsas_smhba_set_all_phy_props(mptsas_t *mpt, dev_info_t *dip,
+ uint8_t phy_nums, mptsas_phymask_t phy_mask, uint16_t *attached_devhdl);
+void mptsas_smhba_set_one_phy_props(mptsas_t *mpt, dev_info_t *dip,
+ uint8_t phy_id, uint16_t *attached_devhdl);
void mptsas_smhba_log_sysevent(mptsas_t *mpt, char *subclass, char *etype,
smhba_info_t *phyp);
void