--- /dev/null	2015-05-20 11:04:08.000000000 -0400
+++ new/usr/src/cmd/make/bin/make/common/files.cc	2015-05-20 11:04:08.308140095 -0400
@@ -0,0 +1,733 @@
+/*
+ * 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 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * @(#)files.cc 1.37 06/12/12
+ */
+
+#pragma	ident	"@(#)files.cc	1.37	06/12/12"
+
+/*
+ *	files.c
+ *
+ *	Various file related routines:
+ *		Figure out if file exists
+ *		Wildcard resolution for directory reader
+ *		Directory reader
+ */
+
+
+/*
+ * Included files
+ */
+#if defined(SUN5_0) || defined(HP_UX)
+#include <dirent.h>		/* opendir() */
+#else
+#include <sys/dir.h>		/* opendir() */
+#endif
+#include <errno.h>		/* errno */
+#include <mk/defs.h>
+#include <mksh/macro.h>		/* getvar() */
+#include <mksh/misc.h>		/* get_prop(), append_prop() */
+#include <sys/stat.h>		/* lstat() */
+
+/*
+ * Defined macros
+ */
+
+/*
+ * typedefs & structs
+ */
+
+/*
+ * Static variables
+ */
+
+/*
+ * File table of contents
+ */
+extern	timestruc_t&	exists(register Name target);
+extern  void		set_target_stat(register Name target, struct stat buf);
+static	timestruc_t&	vpath_exists(register Name target);
+static	Name		enter_file_name(wchar_t *name_string, wchar_t *library);
+static	Boolean		star_match(register char *string, register char *pattern);
+static	Boolean		amatch(register wchar_t *string, register wchar_t *pattern);
+  
+/*
+ *	exists(target)
+ *
+ *	Figure out the timestamp for one target.
+ *
+ *	Return value:
+ *				The time the target was created
+ *
+ *	Parameters:
+ *		target		The target to check
+ *
+ *	Global variables used:
+ *		debug_level	Should we trace the stat call?
+ *		recursion_level	Used for tracing
+ *		vpath_defined	Was the variable VPATH defined in environment?
+ */
+timestruc_t&
+exists(register Name target)
+{
+	struct stat		buf;
+	register int		result;
+
+	/* We cache stat information. */
+	if (target->stat.time != file_no_time) {
+		return target->stat.time;
+	}
+
+	/*
+	 * If the target is a member, we have to extract the time
+	 * from the archive.
+	 */
+	if (target->is_member &&
+	    (get_prop(target->prop, member_prop) != NULL)) {
+		return read_archive(target);
+	}
+
+	if (debug_level > 1) {
+		(void) printf(NOCATGETS("%*sstat(%s)\n"),
+		              recursion_level,
+		              "",
+		              target->string_mb);
+	}
+
+	result = lstat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT);
+	if ((result != -1) && ((buf.st_mode & S_IFMT) == S_IFLNK)) {
+                /*
+		 * If the file is a symbolic link, we remember that
+		 * and then we get the status for the refd file.
+		 */
+                target->stat.is_sym_link = true;
+                result = stat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT);
+        } else {
+                target->stat.is_sym_link = false;
+	}
+
+	if (result < 0) {
+		target->stat.time = file_doesnt_exist;
+		target->stat.stat_errno = errno;
+		if ((errno == ENOENT) &&
+		    vpath_defined &&
+/* azv, fixing bug 1262942, VPATH works with a leaf name
+ * but not a directory name.
+ */
+		    (target->string_mb[0] != (int) slash_char) ) {
+/* BID_1214655 */
+/* azv */
+			vpath_exists(target);
+			// return vpath_exists(target);
+		}
+	} else {
+		/* Save all the information we need about the file */
+		target->stat.stat_errno = 0;
+		target->stat.is_file = true;
+		target->stat.mode = buf.st_mode & 0777;
+		target->stat.size = buf.st_size;
+		target->stat.is_dir =
+		  BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR);
+		if (target->stat.is_dir) {
+			target->stat.time = file_is_dir;
+		} else {
+			/* target->stat.time = buf.st_mtime; */
+/* BID_1129806 */
+/* vis@nbsp.nsk.su */
+#if defined(linux)
+			timestruc_t ttime = { buf.st_mtime, 0 };
+			target->stat.time = MAX(ttime, file_min_time);
+#else
+			target->stat.time = MAX(buf.st_mtim, file_min_time);
+#endif
+		}
+	}
+	if ((target->colon_splits > 0) &&
+	    (get_prop(target->prop, time_prop) == NULL)) {
+		append_prop(target, time_prop)->body.time.time =
+		  target->stat.time;
+	}
+	return target->stat.time;
+}
+
+/*
+ *	set_target_stat( target, buf)
+ *
+ *	Called by exists() to set some stat fields in the Name structure
+ *	to those read by the stat_vroot() call (from disk).
+ *
+ *	Parameters:
+ *		target		The target whose stat field is set
+ *		buf		stat values (on disk) of the file
+ *				represented by target.
+ */
+void
+set_target_stat(register Name target, struct stat buf)
+{
+	target->stat.stat_errno = 0;
+	target->stat.is_file = true;
+	target->stat.mode = buf.st_mode & 0777;
+	target->stat.size = buf.st_size;
+	target->stat.is_dir =
+	  BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR);
+	if (target->stat.is_dir) {
+		target->stat.time = file_is_dir;
+	} else {
+		/* target->stat.time = buf.st_mtime; */
+/* BID_1129806 */
+/* vis@nbsp.nsk.su */
+#if defined(linux)
+		timestruc_t ttime = { buf.st_mtime, 0 };
+		target->stat.time = ttime;
+#else
+		target->stat.time = MAX(buf.st_mtim, file_min_time);
+#endif
+	}
+}
+
+
+/*
+ *	vpath_exists(target)
+ *
+ *	Called if exists() discovers that there is a VPATH defined.
+ *	This function stats the VPATH translation of the target.
+ *
+ *	Return value:
+ *				The time the target was created
+ *
+ *	Parameters:
+ *		target		The target to check
+ *
+ *	Global variables used:
+ *		vpath_name	The Name "VPATH", used to get macro value
+ */
+static timestruc_t&
+vpath_exists(register Name target)
+{
+	wchar_t			*vpath;
+	wchar_t			file_name[MAXPATHLEN];
+	wchar_t			*name_p;
+	Name			alias;
+
+	/*
+	 * To avoid recursive search through VPATH when exists(alias) is called
+	 */
+	vpath_defined = false;
+
+	Wstring wcb(getvar(vpath_name));
+	Wstring wcb1(target);
+
+	vpath = wcb.get_string();
+
+	while (*vpath != (int) nul_char) {
+		name_p = file_name;
+		while ((*vpath != (int) colon_char) &&
+		       (*vpath != (int) nul_char)) {
+			*name_p++ = *vpath++;
+		}
+		*name_p++ = (int) slash_char;
+		(void) wscpy(name_p, wcb1.get_string());
+		alias = GETNAME(file_name, FIND_LENGTH);
+		if (exists(alias) != file_doesnt_exist) {
+			target->stat.is_file = true;
+			target->stat.mode = alias->stat.mode;
+			target->stat.size = alias->stat.size;
+			target->stat.is_dir = alias->stat.is_dir;
+			target->stat.time = alias->stat.time;
+			maybe_append_prop(target, vpath_alias_prop)->
+						body.vpath_alias.alias = alias;
+			target->has_vpath_alias_prop = true;
+			vpath_defined = true;
+			return alias->stat.time;
+		}
+		while ((*vpath != (int) nul_char) &&
+		       ((*vpath == (int) colon_char) || iswspace(*vpath))) {
+			vpath++;
+		}
+	}
+	/*
+	 * Restore vpath_defined
+	 */
+	vpath_defined = true;
+	return target->stat.time;
+}
+
+/*
+ *	read_dir(dir, pattern, line, library)
+ *
+ *	Used to enter the contents of directories into makes namespace.
+ *	Presence of a file is important when scanning for implicit rules.
+ *	read_dir() is also used to expand wildcards in dependency lists.
+ *
+ *	Return value:
+ *				Non-0 if we found files to match the pattern
+ *
+ *	Parameters:
+ *		dir		Path to the directory to read
+ *		pattern		Pattern for that files should match or NULL
+ *		line		When we scan using a pattern we enter files
+ *				we find as dependencies for this line
+ *		library		If we scan for "lib.a(<wildcard-member>)"
+ *
+ *	Global variables used:
+ *		debug_level	Should we trace the dir reading?
+ *		dot		The Name ".", compared against
+ *		sccs_dir_path	The path to the SCCS dir (from PROJECTDIR)
+ *		vpath_defined	Was the variable VPATH defined in environment?
+ *		vpath_name	The Name "VPATH", use to get macro value
+ */
+int
+read_dir(Name dir, wchar_t *pattern, Property line, wchar_t *library)
+{
+	wchar_t			file_name[MAXPATHLEN];
+	wchar_t			*file_name_p = file_name;
+	Name			file;
+	wchar_t			plain_file_name[MAXPATHLEN];
+	wchar_t			*plain_file_name_p;
+	Name			plain_file;
+	wchar_t			tmp_wcs_buffer[MAXPATHLEN];
+	DIR			*dir_fd;
+	int			m_local_dependency=0;
+#if defined(SUN5_0) || defined(HP_UX)
+#define d_fileno d_ino
+        register struct dirent  *dp;
+#else
+        register struct direct  *dp;
+#endif
+	wchar_t			*vpath = NULL;
+	wchar_t			*p;
+	int			result = 0;
+
+	if(dir->hash.length >= MAXPATHLEN) {
+		return 0;
+	}
+
+	Wstring wcb(dir);
+	Wstring vps;
+
+	/* A directory is only read once unless we need to expand wildcards. */
+	if (pattern == NULL) {
+		if (dir->has_read_dir) {
+			return 0;
+		}
+		dir->has_read_dir = true;
+	}
+	/* Check if VPATH is active and setup list if it is. */
+	if (vpath_defined && (dir == dot)) {
+		vps.init(getvar(vpath_name));
+		vpath = vps.get_string();
+	}
+
+	/*
+	 * Prepare the string where we build the full name of the
+	 * files in the directory.
+	 */
+	if ((dir->hash.length > 1) || (wcb.get_string()[0] != (int) period_char)) {
+		(void) wscpy(file_name, wcb.get_string());
+		MBSTOWCS(wcs_buffer, "/");
+		(void) wscat(file_name, wcs_buffer);
+		file_name_p = file_name + wslen(file_name);
+	}
+
+	/* Open the directory. */
+vpath_loop:
+	dir_fd = opendir(dir->string_mb);
+	if (dir_fd == NULL) {
+		return 0;
+	}
+
+	/* Read all the directory entries. */
+	while ((dp = readdir(dir_fd)) != NULL) {
+		/* We ignore "." and ".." */
+		if ((dp->d_fileno == 0) ||
+		    ((dp->d_name[0] == (int) period_char) &&
+		     ((dp->d_name[1] == 0) ||
+		      ((dp->d_name[1] == (int) period_char) &&
+		       (dp->d_name[2] == 0))))) {
+			continue;
+		}
+		/*
+		 * Build the full name of the file using whatever
+		 * path supplied to the function.
+		 */
+		MBSTOWCS(tmp_wcs_buffer, dp->d_name);
+		(void) wscpy(file_name_p, tmp_wcs_buffer);
+		file = enter_file_name(file_name, library);
+		if ((pattern != NULL) && amatch(tmp_wcs_buffer, pattern)) {
+			/*
+			 * If we are expanding a wildcard pattern, we
+			 * enter the file as a dependency for the target.
+			 */
+			if (debug_level > 0){
+				WCSTOMBS(mbs_buffer, pattern);
+				(void) printf(catgets(catd, 1, 231, "'%s: %s' due to %s expansion\n"),
+					      line->body.line.target->string_mb,
+					      file->string_mb,
+					      mbs_buffer);
+			}
+			enter_dependency(line, file, false);
+			result++;
+		} else {
+			/*
+			 * If the file has an SCCS/s. file,
+			 * we will detect that later on.
+			 */
+			file->stat.has_sccs = NO_SCCS;
+		/*
+		 * If this is an s. file, we also enter it as if it
+		 * existed in the plain directory.
+		 */
+		if ((dp->d_name[0] == 's') &&
+		    (dp->d_name[1] == (int) period_char)) {
+	
+			MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
+			plain_file_name_p = plain_file_name;
+			(void) wscpy(plain_file_name_p, tmp_wcs_buffer);
+			plain_file = GETNAME(plain_file_name, FIND_LENGTH);
+			plain_file->stat.is_file = true;
+			plain_file->stat.has_sccs = HAS_SCCS;
+			/*
+			 * Enter the s. file as a dependency for the
+			 * plain file.
+			 */
+			maybe_append_prop(plain_file, sccs_prop)->
+			  body.sccs.file = file;
+			MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
+			if ((pattern != NULL) &&
+			    amatch(tmp_wcs_buffer, pattern)) {
+				if (debug_level > 0) {
+					WCSTOMBS(mbs_buffer, pattern);
+					(void) printf(catgets(catd, 1, 232, "'%s: %s' due to %s expansion\n"),
+						      line->body.line.target->
+						      string_mb,
+						      plain_file->string_mb,
+						      mbs_buffer);
+				}
+				enter_dependency(line, plain_file, false);
+				result++;
+			}
+		}
+	      }
+	}
+	(void) closedir(dir_fd);
+	if ((vpath != NULL) && (*vpath != (int) nul_char)) {
+		while ((*vpath != (int) nul_char) &&
+		       (iswspace(*vpath) || (*vpath == (int) colon_char))) {
+			vpath++;
+		}
+		p = vpath;
+		while ((*vpath != (int) colon_char) &&
+		       (*vpath != (int) nul_char)) {
+			vpath++;
+		}
+		if (vpath > p) {
+			dir = GETNAME(p, vpath - p);
+			goto vpath_loop;
+		}
+	}
+/*
+ * look into SCCS directory only if it's not svr4. For svr4 dont do that.
+ */
+
+/*
+ * Now read the SCCS directory.
+ * Files in the SCSC directory are considered to be part of the set of
+ * files in the plain directory. They are also entered in their own right.
+ * Prepare the string where we build the true name of the SCCS files.
+ */
+	(void) wsncpy(plain_file_name,
+		      file_name,
+		      file_name_p - file_name);
+	plain_file_name[file_name_p - file_name] = 0;
+	plain_file_name_p = plain_file_name + wslen(plain_file_name);
+
+        if(!svr4) {
+
+	  if (sccs_dir_path != NULL) {
+		wchar_t		tmp_wchar;
+		wchar_t		path[MAXPATHLEN];
+		char		mb_path[MAXPATHLEN];
+
+		if (file_name_p - file_name > 0) {
+			tmp_wchar = *file_name_p;
+			*file_name_p = 0;
+			WCSTOMBS(mbs_buffer, file_name);
+			(void) sprintf(mb_path, NOCATGETS("%s/%s/SCCS"),
+				        sccs_dir_path,
+				        mbs_buffer);
+			*file_name_p = tmp_wchar;
+		} else {
+			(void) sprintf(mb_path, NOCATGETS("%s/SCCS"), sccs_dir_path);
+		}
+		MBSTOWCS(path, mb_path);
+		(void) wscpy(file_name, path);
+	  } else {
+		MBSTOWCS(wcs_buffer, NOCATGETS("SCCS"));
+		(void) wscpy(file_name_p, wcs_buffer);
+	  }
+	} else {
+		MBSTOWCS(wcs_buffer, NOCATGETS("."));
+		(void) wscpy(file_name_p, wcs_buffer);
+	}
+	/* Internalize the constructed SCCS dir name. */
+	(void) exists(dir = GETNAME(file_name, FIND_LENGTH));
+	/* Just give up if the directory file doesnt exist. */
+	if (!dir->stat.is_file) {
+		return result;
+	}
+	/* Open the directory. */
+	dir_fd = opendir(dir->string_mb);
+	if (dir_fd == NULL) {
+		return result;
+	}
+	MBSTOWCS(wcs_buffer, "/");
+	(void) wscat(file_name, wcs_buffer);
+	file_name_p = file_name + wslen(file_name);
+
+	while ((dp = readdir(dir_fd)) != NULL) {
+		if ((dp->d_fileno == 0) ||
+		    ((dp->d_name[0] == (int) period_char) &&
+		     ((dp->d_name[1] == 0) ||
+		      ((dp->d_name[1] == (int) period_char) &&
+		       (dp->d_name[2] == 0))))) {
+			continue;
+		}
+		/* Construct and internalize the true name of the SCCS file. */
+		MBSTOWCS(wcs_buffer, dp->d_name);
+		(void) wscpy(file_name_p, wcs_buffer);
+		file = GETNAME(file_name, FIND_LENGTH);
+		file->stat.is_file = true;
+		file->stat.has_sccs = NO_SCCS;
+		/*
+		 * If this is an s. file, we also enter it as if it
+		 * existed in the plain directory.
+		 */
+		if ((dp->d_name[0] == 's') &&
+		    (dp->d_name[1] == (int) period_char)) {
+	
+			MBSTOWCS(wcs_buffer, dp->d_name + 2);
+			(void) wscpy(plain_file_name_p, wcs_buffer);
+			plain_file = GETNAME(plain_file_name, FIND_LENGTH);
+			plain_file->stat.is_file = true;
+			plain_file->stat.has_sccs = HAS_SCCS;
+				/* if sccs dependency is already set,skip */
+			if(plain_file->prop) {
+				Property sprop = get_prop(plain_file->prop,sccs_prop);
+				if(sprop != NULL) {
+					if (sprop->body.sccs.file) {
+						goto try_pattern;
+					}
+				}
+			}
+
+			/*
+			 * Enter the s. file as a dependency for the
+			 * plain file.
+			 */
+			maybe_append_prop(plain_file, sccs_prop)->
+			  body.sccs.file = file;
+try_pattern:
+			MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
+			if ((pattern != NULL) &&
+			    amatch(tmp_wcs_buffer, pattern)) {
+				if (debug_level > 0) {
+					WCSTOMBS(mbs_buffer, pattern);
+					(void) printf(catgets(catd, 1, 233, "'%s: %s' due to %s expansion\n"),
+						      line->body.line.target->
+						      string_mb,
+						      plain_file->string_mb,
+						      mbs_buffer);
+				}
+				enter_dependency(line, plain_file, false);
+				result++;
+			}
+		}
+	}
+	(void) closedir(dir_fd);
+
+	return result;
+}
+
+/*
+ *	enter_file_name(name_string, library)
+ *
+ *	Helper function for read_dir().
+ *
+ *	Return value:
+ *				The Name that was entered
+ *
+ *	Parameters:
+ *		name_string	Name of the file we want to enter
+ *		library		The library it is a member of, if any
+ *
+ *	Global variables used:
+ */
+static Name
+enter_file_name(wchar_t *name_string, wchar_t *library)
+{
+	wchar_t		buffer[STRING_BUFFER_LENGTH];
+	String_rec	lib_name;
+	Name		name;
+	Property	prop;
+
+	if (library == NULL) {
+		name = GETNAME(name_string, FIND_LENGTH);
+		name->stat.is_file = true;
+		return name;
+	}
+
+	INIT_STRING_FROM_STACK(lib_name, buffer);
+	append_string(library, &lib_name, FIND_LENGTH);
+	append_char((int) parenleft_char, &lib_name);
+	append_string(name_string, &lib_name, FIND_LENGTH);
+	append_char((int) parenright_char, &lib_name);
+
+	name = GETNAME(lib_name.buffer.start, FIND_LENGTH);
+	name->stat.is_file = true;
+	name->is_member = true;
+	prop = maybe_append_prop(name, member_prop);
+	prop->body.member.library = GETNAME(library, FIND_LENGTH);
+	prop->body.member.library->stat.is_file = true;
+	prop->body.member.entry = NULL;
+	prop->body.member.member = GETNAME(name_string, FIND_LENGTH);
+	prop->body.member.member->stat.is_file = true;
+	return name;
+}
+
+/*
+ *	star_match(string, pattern)
+ *
+ *	This is a regular shell type wildcard pattern matcher
+ *	It is used when xpanding wildcards in dependency lists
+ *
+ *	Return value:
+ *				Indication if the string matched the pattern
+ *
+ *	Parameters:
+ *		string		String to match
+ *		pattern		Pattern to match it against
+ *
+ *	Global variables used:
+ */
+static Boolean
+star_match(register wchar_t *string, register wchar_t *pattern)
+{
+	register int		pattern_ch;
+
+	switch (*pattern) {
+	case 0:
+		return succeeded;
+	case bracketleft_char:
+	case question_char:
+	case asterisk_char:
+		while (*string) {
+			if (amatch(string++, pattern)) {
+				return succeeded;
+			}
+		}
+		break;
+	default:
+		pattern_ch = (int) *pattern++;
+		while (*string) {
+			if ((*string++ == pattern_ch) &&
+			    amatch(string, pattern)) {
+				return succeeded;
+			}
+		}
+		break;
+	}
+	return failed;
+}
+
+/*
+ *	amatch(string, pattern)
+ *
+ *	Helper function for shell pattern matching
+ *
+ *	Return value:
+ *				Indication if the string matched the pattern
+ *
+ *	Parameters:
+ *		string		String to match
+ *		pattern		Pattern to match it against
+ *
+ *	Global variables used:
+ */
+static Boolean
+amatch(register wchar_t *string, register wchar_t *pattern)
+{
+	register long		lower_bound;
+	register long		string_ch;
+	register long		pattern_ch;
+	register int		k;
+
+top:
+	for (; 1; pattern++, string++) {
+		lower_bound = 017777777777;
+		string_ch = *string;
+		switch (pattern_ch = *pattern) {
+		case bracketleft_char:
+			k = 0;
+			while ((pattern_ch = *++pattern) != 0) {
+				switch (pattern_ch) {
+				case bracketright_char:
+					if (!k) {
+						return failed;
+					}
+					string++;
+					pattern++;
+					goto top;
+				case hyphen_char:
+					k |= (lower_bound <= string_ch) &&
+					     (string_ch <=
+					      (pattern_ch = pattern[1]));
+				default:
+					if (string_ch ==
+					    (lower_bound = pattern_ch)) {
+						k++;
+					}
+				}
+			}
+			return failed;
+		case asterisk_char:
+			return star_match(string, ++pattern);
+		case 0:
+			return BOOLEAN(!string_ch);
+		case question_char:
+			if (string_ch == 0) {
+				return failed;
+			}
+			break;
+		default:
+			if (pattern_ch != string_ch) {
+				return failed;
+			}
+			break;
+		}
+	}
+	/* NOTREACHED */
+}
+
