xref: /illumos-gate/usr/src/cmd/make/bin/files.cc (revision e7afc443)
110d63b7dSRichard Lowe /*
210d63b7dSRichard Lowe  * CDDL HEADER START
310d63b7dSRichard Lowe  *
410d63b7dSRichard Lowe  * The contents of this file are subject to the terms of the
510d63b7dSRichard Lowe  * Common Development and Distribution License (the "License").
610d63b7dSRichard Lowe  * You may not use this file except in compliance with the License.
710d63b7dSRichard Lowe  *
810d63b7dSRichard Lowe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910d63b7dSRichard Lowe  * or http://www.opensolaris.org/os/licensing.
1010d63b7dSRichard Lowe  * See the License for the specific language governing permissions
1110d63b7dSRichard Lowe  * and limitations under the License.
1210d63b7dSRichard Lowe  *
1310d63b7dSRichard Lowe  * When distributing Covered Code, include this CDDL HEADER in each
1410d63b7dSRichard Lowe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510d63b7dSRichard Lowe  * If applicable, add the following below this CDDL HEADER, with the
1610d63b7dSRichard Lowe  * fields enclosed by brackets "[]" replaced with your own identifying
1710d63b7dSRichard Lowe  * information: Portions Copyright [yyyy] [name of copyright owner]
1810d63b7dSRichard Lowe  *
1910d63b7dSRichard Lowe  * CDDL HEADER END
2010d63b7dSRichard Lowe  */
2110d63b7dSRichard Lowe /*
2210d63b7dSRichard Lowe  * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
2310d63b7dSRichard Lowe  * Use is subject to license terms.
248e0c8248SAndrew Stormont  *
258e0c8248SAndrew Stormont  * Copyright 2019 RackTop Systems.
2610d63b7dSRichard Lowe  */
2710d63b7dSRichard Lowe 
2810d63b7dSRichard Lowe /*
2910d63b7dSRichard Lowe  *	files.c
3010d63b7dSRichard Lowe  *
3110d63b7dSRichard Lowe  *	Various file related routines:
3210d63b7dSRichard Lowe  *		Figure out if file exists
3310d63b7dSRichard Lowe  *		Wildcard resolution for directory reader
3410d63b7dSRichard Lowe  *		Directory reader
3510d63b7dSRichard Lowe  */
3610d63b7dSRichard Lowe 
3710d63b7dSRichard Lowe 
3810d63b7dSRichard Lowe /*
3910d63b7dSRichard Lowe  * Included files
4010d63b7dSRichard Lowe  */
4110d63b7dSRichard Lowe #include <dirent.h>		/* opendir() */
4210d63b7dSRichard Lowe #include <errno.h>		/* errno */
4310d63b7dSRichard Lowe #include <mk/defs.h>
4410d63b7dSRichard Lowe #include <mksh/macro.h>		/* getvar() */
4510d63b7dSRichard Lowe #include <mksh/misc.h>		/* get_prop(), append_prop() */
4610d63b7dSRichard Lowe #include <sys/stat.h>		/* lstat() */
4710d63b7dSRichard Lowe #include <libintl.h>
4810d63b7dSRichard Lowe 
4910d63b7dSRichard Lowe /*
5010d63b7dSRichard Lowe  * Defined macros
5110d63b7dSRichard Lowe  */
5210d63b7dSRichard Lowe 
5310d63b7dSRichard Lowe /*
5410d63b7dSRichard Lowe  * typedefs & structs
5510d63b7dSRichard Lowe  */
5610d63b7dSRichard Lowe 
5710d63b7dSRichard Lowe /*
5810d63b7dSRichard Lowe  * Static variables
5910d63b7dSRichard Lowe  */
6010d63b7dSRichard Lowe 
6110d63b7dSRichard Lowe /*
6210d63b7dSRichard Lowe  * File table of contents
6310d63b7dSRichard Lowe  */
64*e7afc443SToomas Soome extern	timestruc_t&	exists(Name target);
65*e7afc443SToomas Soome extern  void		set_target_stat(Name target, struct stat buf);
66*e7afc443SToomas Soome static	timestruc_t&	vpath_exists(Name target);
6710d63b7dSRichard Lowe static	Name		enter_file_name(wchar_t *name_string, wchar_t *library);
68*e7afc443SToomas Soome static	Boolean		star_match(char *string, char *pattern);
69*e7afc443SToomas Soome static	Boolean		amatch(wchar_t *string, wchar_t *pattern);
7010d63b7dSRichard Lowe 
7110d63b7dSRichard Lowe /*
7210d63b7dSRichard Lowe  *	exists(target)
7310d63b7dSRichard Lowe  *
7410d63b7dSRichard Lowe  *	Figure out the timestamp for one target.
7510d63b7dSRichard Lowe  *
7610d63b7dSRichard Lowe  *	Return value:
7710d63b7dSRichard Lowe  *				The time the target was created
7810d63b7dSRichard Lowe  *
7910d63b7dSRichard Lowe  *	Parameters:
8010d63b7dSRichard Lowe  *		target		The target to check
8110d63b7dSRichard Lowe  *
8210d63b7dSRichard Lowe  *	Global variables used:
8310d63b7dSRichard Lowe  *		debug_level	Should we trace the stat call?
8410d63b7dSRichard Lowe  *		recursion_level	Used for tracing
8510d63b7dSRichard Lowe  *		vpath_defined	Was the variable VPATH defined in environment?
8610d63b7dSRichard Lowe  */
8710d63b7dSRichard Lowe timestruc_t&
exists(Name target)88*e7afc443SToomas Soome exists(Name target)
8910d63b7dSRichard Lowe {
9010d63b7dSRichard Lowe 	struct stat		buf;
91*e7afc443SToomas Soome 	int		result;
9210d63b7dSRichard Lowe 
9310d63b7dSRichard Lowe 	/* We cache stat information. */
9410d63b7dSRichard Lowe 	if (target->stat.time != file_no_time) {
9510d63b7dSRichard Lowe 		return target->stat.time;
9610d63b7dSRichard Lowe 	}
9710d63b7dSRichard Lowe 
9810d63b7dSRichard Lowe 	/*
9910d63b7dSRichard Lowe 	 * If the target is a member, we have to extract the time
10010d63b7dSRichard Lowe 	 * from the archive.
10110d63b7dSRichard Lowe 	 */
10210d63b7dSRichard Lowe 	if (target->is_member &&
10310d63b7dSRichard Lowe 	    (get_prop(target->prop, member_prop) != NULL)) {
10410d63b7dSRichard Lowe 		return read_archive(target);
10510d63b7dSRichard Lowe 	}
10610d63b7dSRichard Lowe 
10710d63b7dSRichard Lowe 	if (debug_level > 1) {
10810d63b7dSRichard Lowe 		(void) printf("%*sstat(%s)\n",
10910d63b7dSRichard Lowe 		              recursion_level,
11010d63b7dSRichard Lowe 		              "",
11110d63b7dSRichard Lowe 		              target->string_mb);
11210d63b7dSRichard Lowe 	}
11310d63b7dSRichard Lowe 
11410d63b7dSRichard Lowe 	result = lstat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT);
11510d63b7dSRichard Lowe 	if ((result != -1) && ((buf.st_mode & S_IFMT) == S_IFLNK)) {
11610d63b7dSRichard Lowe                 /*
11710d63b7dSRichard Lowe 		 * If the file is a symbolic link, we remember that
11810d63b7dSRichard Lowe 		 * and then we get the status for the refd file.
11910d63b7dSRichard Lowe 		 */
12010d63b7dSRichard Lowe                 target->stat.is_sym_link = true;
12110d63b7dSRichard Lowe                 result = stat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT);
12210d63b7dSRichard Lowe         } else {
12310d63b7dSRichard Lowe                 target->stat.is_sym_link = false;
12410d63b7dSRichard Lowe 	}
12510d63b7dSRichard Lowe 
12610d63b7dSRichard Lowe 	if (result < 0) {
12710d63b7dSRichard Lowe 		target->stat.time = file_doesnt_exist;
12810d63b7dSRichard Lowe 		target->stat.stat_errno = errno;
12910d63b7dSRichard Lowe 		if ((errno == ENOENT) &&
13010d63b7dSRichard Lowe 		    vpath_defined &&
13110d63b7dSRichard Lowe /* azv, fixing bug 1262942, VPATH works with a leaf name
13210d63b7dSRichard Lowe  * but not a directory name.
13310d63b7dSRichard Lowe  */
13410d63b7dSRichard Lowe 		    (target->string_mb[0] != (int) slash_char) ) {
13510d63b7dSRichard Lowe /* BID_1214655 */
13610d63b7dSRichard Lowe /* azv */
13710d63b7dSRichard Lowe 			vpath_exists(target);
13810d63b7dSRichard Lowe 			// return vpath_exists(target);
13910d63b7dSRichard Lowe 		}
14010d63b7dSRichard Lowe 	} else {
14110d63b7dSRichard Lowe 		/* Save all the information we need about the file */
14210d63b7dSRichard Lowe 		target->stat.stat_errno = 0;
14310d63b7dSRichard Lowe 		target->stat.is_file = true;
14410d63b7dSRichard Lowe 		target->stat.mode = buf.st_mode & 0777;
14510d63b7dSRichard Lowe 		target->stat.size = buf.st_size;
14610d63b7dSRichard Lowe 		target->stat.is_dir =
14710d63b7dSRichard Lowe 		  BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR);
14810d63b7dSRichard Lowe 		if (target->stat.is_dir) {
14910d63b7dSRichard Lowe 			target->stat.time = file_is_dir;
15010d63b7dSRichard Lowe 		} else {
15110d63b7dSRichard Lowe 			/* target->stat.time = buf.st_mtime; */
15210d63b7dSRichard Lowe /* BID_1129806 */
15310d63b7dSRichard Lowe /* vis@nbsp.nsk.su */
15410d63b7dSRichard Lowe 			target->stat.time = MAX(buf.st_mtim, file_min_time);
15510d63b7dSRichard Lowe 		}
15610d63b7dSRichard Lowe 	}
15710d63b7dSRichard Lowe 	if ((target->colon_splits > 0) &&
15810d63b7dSRichard Lowe 	    (get_prop(target->prop, time_prop) == NULL)) {
15910d63b7dSRichard Lowe 		append_prop(target, time_prop)->body.time.time =
16010d63b7dSRichard Lowe 		  target->stat.time;
16110d63b7dSRichard Lowe 	}
16210d63b7dSRichard Lowe 	return target->stat.time;
16310d63b7dSRichard Lowe }
16410d63b7dSRichard Lowe 
16510d63b7dSRichard Lowe /*
16610d63b7dSRichard Lowe  *	set_target_stat( target, buf)
16710d63b7dSRichard Lowe  *
16810d63b7dSRichard Lowe  *	Called by exists() to set some stat fields in the Name structure
16910d63b7dSRichard Lowe  *	to those read by the stat_vroot() call (from disk).
17010d63b7dSRichard Lowe  *
17110d63b7dSRichard Lowe  *	Parameters:
17210d63b7dSRichard Lowe  *		target		The target whose stat field is set
17310d63b7dSRichard Lowe  *		buf		stat values (on disk) of the file
17410d63b7dSRichard Lowe  *				represented by target.
17510d63b7dSRichard Lowe  */
17610d63b7dSRichard Lowe void
set_target_stat(Name target,struct stat buf)177*e7afc443SToomas Soome set_target_stat(Name target, struct stat buf)
17810d63b7dSRichard Lowe {
17910d63b7dSRichard Lowe 	target->stat.stat_errno = 0;
18010d63b7dSRichard Lowe 	target->stat.is_file = true;
18110d63b7dSRichard Lowe 	target->stat.mode = buf.st_mode & 0777;
18210d63b7dSRichard Lowe 	target->stat.size = buf.st_size;
18310d63b7dSRichard Lowe 	target->stat.is_dir =
18410d63b7dSRichard Lowe 	  BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR);
18510d63b7dSRichard Lowe 	if (target->stat.is_dir) {
18610d63b7dSRichard Lowe 		target->stat.time = file_is_dir;
18710d63b7dSRichard Lowe 	} else {
18810d63b7dSRichard Lowe 		/* target->stat.time = buf.st_mtime; */
18910d63b7dSRichard Lowe /* BID_1129806 */
19010d63b7dSRichard Lowe /* vis@nbsp.nsk.su */
19110d63b7dSRichard Lowe 		target->stat.time = MAX(buf.st_mtim, file_min_time);
19210d63b7dSRichard Lowe 	}
19310d63b7dSRichard Lowe }
19410d63b7dSRichard Lowe 
19510d63b7dSRichard Lowe 
19610d63b7dSRichard Lowe /*
19710d63b7dSRichard Lowe  *	vpath_exists(target)
19810d63b7dSRichard Lowe  *
19910d63b7dSRichard Lowe  *	Called if exists() discovers that there is a VPATH defined.
20010d63b7dSRichard Lowe  *	This function stats the VPATH translation of the target.
20110d63b7dSRichard Lowe  *
20210d63b7dSRichard Lowe  *	Return value:
20310d63b7dSRichard Lowe  *				The time the target was created
20410d63b7dSRichard Lowe  *
20510d63b7dSRichard Lowe  *	Parameters:
20610d63b7dSRichard Lowe  *		target		The target to check
20710d63b7dSRichard Lowe  *
20810d63b7dSRichard Lowe  *	Global variables used:
20910d63b7dSRichard Lowe  *		vpath_name	The Name "VPATH", used to get macro value
21010d63b7dSRichard Lowe  */
21110d63b7dSRichard Lowe static timestruc_t&
vpath_exists(Name target)212*e7afc443SToomas Soome vpath_exists(Name target)
21310d63b7dSRichard Lowe {
21410d63b7dSRichard Lowe 	wchar_t			*vpath;
21510d63b7dSRichard Lowe 	wchar_t			file_name[MAXPATHLEN];
21610d63b7dSRichard Lowe 	wchar_t			*name_p;
21710d63b7dSRichard Lowe 	Name			alias;
21810d63b7dSRichard Lowe 
21910d63b7dSRichard Lowe 	/*
22010d63b7dSRichard Lowe 	 * To avoid recursive search through VPATH when exists(alias) is called
22110d63b7dSRichard Lowe 	 */
22210d63b7dSRichard Lowe 	vpath_defined = false;
22310d63b7dSRichard Lowe 
22410d63b7dSRichard Lowe 	Wstring wcb(getvar(vpath_name));
22510d63b7dSRichard Lowe 	Wstring wcb1(target);
22610d63b7dSRichard Lowe 
22710d63b7dSRichard Lowe 	vpath = wcb.get_string();
22810d63b7dSRichard Lowe 
22910d63b7dSRichard Lowe 	while (*vpath != (int) nul_char) {
23010d63b7dSRichard Lowe 		name_p = file_name;
23110d63b7dSRichard Lowe 		while ((*vpath != (int) colon_char) &&
23210d63b7dSRichard Lowe 		       (*vpath != (int) nul_char)) {
23310d63b7dSRichard Lowe 			*name_p++ = *vpath++;
23410d63b7dSRichard Lowe 		}
23510d63b7dSRichard Lowe 		*name_p++ = (int) slash_char;
23610d63b7dSRichard Lowe 		(void) wcscpy(name_p, wcb1.get_string());
23710d63b7dSRichard Lowe 		alias = GETNAME(file_name, FIND_LENGTH);
23810d63b7dSRichard Lowe 		if (exists(alias) != file_doesnt_exist) {
23910d63b7dSRichard Lowe 			target->stat.is_file = true;
24010d63b7dSRichard Lowe 			target->stat.mode = alias->stat.mode;
24110d63b7dSRichard Lowe 			target->stat.size = alias->stat.size;
24210d63b7dSRichard Lowe 			target->stat.is_dir = alias->stat.is_dir;
24310d63b7dSRichard Lowe 			target->stat.time = alias->stat.time;
24410d63b7dSRichard Lowe 			maybe_append_prop(target, vpath_alias_prop)->
24510d63b7dSRichard Lowe 						body.vpath_alias.alias = alias;
24610d63b7dSRichard Lowe 			target->has_vpath_alias_prop = true;
24710d63b7dSRichard Lowe 			vpath_defined = true;
24810d63b7dSRichard Lowe 			return alias->stat.time;
24910d63b7dSRichard Lowe 		}
25010d63b7dSRichard Lowe 		while ((*vpath != (int) nul_char) &&
25110d63b7dSRichard Lowe 		       ((*vpath == (int) colon_char) || iswspace(*vpath))) {
25210d63b7dSRichard Lowe 			vpath++;
25310d63b7dSRichard Lowe 		}
25410d63b7dSRichard Lowe 	}
25510d63b7dSRichard Lowe 	/*
25610d63b7dSRichard Lowe 	 * Restore vpath_defined
25710d63b7dSRichard Lowe 	 */
25810d63b7dSRichard Lowe 	vpath_defined = true;
25910d63b7dSRichard Lowe 	return target->stat.time;
26010d63b7dSRichard Lowe }
26110d63b7dSRichard Lowe 
26210d63b7dSRichard Lowe /*
26310d63b7dSRichard Lowe  *	read_dir(dir, pattern, line, library)
26410d63b7dSRichard Lowe  *
26510d63b7dSRichard Lowe  *	Used to enter the contents of directories into makes namespace.
26610d63b7dSRichard Lowe  *	Presence of a file is important when scanning for implicit rules.
26710d63b7dSRichard Lowe  *	read_dir() is also used to expand wildcards in dependency lists.
26810d63b7dSRichard Lowe  *
26910d63b7dSRichard Lowe  *	Return value:
27010d63b7dSRichard Lowe  *				Non-0 if we found files to match the pattern
27110d63b7dSRichard Lowe  *
27210d63b7dSRichard Lowe  *	Parameters:
27310d63b7dSRichard Lowe  *		dir		Path to the directory to read
27410d63b7dSRichard Lowe  *		pattern		Pattern for that files should match or NULL
27510d63b7dSRichard Lowe  *		line		When we scan using a pattern we enter files
27610d63b7dSRichard Lowe  *				we find as dependencies for this line
27710d63b7dSRichard Lowe  *		library		If we scan for "lib.a(<wildcard-member>)"
27810d63b7dSRichard Lowe  *
27910d63b7dSRichard Lowe  *	Global variables used:
28010d63b7dSRichard Lowe  *		debug_level	Should we trace the dir reading?
28110d63b7dSRichard Lowe  *		dot		The Name ".", compared against
28210d63b7dSRichard Lowe  *		sccs_dir_path	The path to the SCCS dir (from PROJECTDIR)
28310d63b7dSRichard Lowe  *		vpath_defined	Was the variable VPATH defined in environment?
28410d63b7dSRichard Lowe  *		vpath_name	The Name "VPATH", use to get macro value
28510d63b7dSRichard Lowe  */
28610d63b7dSRichard Lowe int
read_dir(Name dir,wchar_t * pattern,Property line,wchar_t * library)28710d63b7dSRichard Lowe read_dir(Name dir, wchar_t *pattern, Property line, wchar_t *library)
28810d63b7dSRichard Lowe {
28910d63b7dSRichard Lowe 	wchar_t			file_name[MAXPATHLEN];
29010d63b7dSRichard Lowe 	wchar_t			*file_name_p = file_name;
29110d63b7dSRichard Lowe 	Name			file;
29210d63b7dSRichard Lowe 	wchar_t			plain_file_name[MAXPATHLEN];
29310d63b7dSRichard Lowe 	wchar_t			*plain_file_name_p;
29410d63b7dSRichard Lowe 	Name			plain_file;
29510d63b7dSRichard Lowe 	wchar_t			tmp_wcs_buffer[MAXPATHLEN];
29610d63b7dSRichard Lowe 	DIR			*dir_fd;
29710d63b7dSRichard Lowe 	int			m_local_dependency=0;
29810d63b7dSRichard Lowe #define d_fileno d_ino
299*e7afc443SToomas Soome         struct dirent  *dp;
30010d63b7dSRichard Lowe 	wchar_t			*vpath = NULL;
30110d63b7dSRichard Lowe 	wchar_t			*p;
30210d63b7dSRichard Lowe 	int			result = 0;
30310d63b7dSRichard Lowe 
30410d63b7dSRichard Lowe 	if(dir->hash.length >= MAXPATHLEN) {
30510d63b7dSRichard Lowe 		return 0;
30610d63b7dSRichard Lowe 	}
30710d63b7dSRichard Lowe 
30810d63b7dSRichard Lowe 	Wstring wcb(dir);
30910d63b7dSRichard Lowe 	Wstring vps;
31010d63b7dSRichard Lowe 
31110d63b7dSRichard Lowe 	/* A directory is only read once unless we need to expand wildcards. */
31210d63b7dSRichard Lowe 	if (pattern == NULL) {
31310d63b7dSRichard Lowe 		if (dir->has_read_dir) {
31410d63b7dSRichard Lowe 			return 0;
31510d63b7dSRichard Lowe 		}
31610d63b7dSRichard Lowe 		dir->has_read_dir = true;
31710d63b7dSRichard Lowe 	}
31810d63b7dSRichard Lowe 	/* Check if VPATH is active and setup list if it is. */
31910d63b7dSRichard Lowe 	if (vpath_defined && (dir == dot)) {
32010d63b7dSRichard Lowe 		vps.init(getvar(vpath_name));
32110d63b7dSRichard Lowe 		vpath = vps.get_string();
32210d63b7dSRichard Lowe 	}
32310d63b7dSRichard Lowe 
32410d63b7dSRichard Lowe 	/*
32510d63b7dSRichard Lowe 	 * Prepare the string where we build the full name of the
32610d63b7dSRichard Lowe 	 * files in the directory.
32710d63b7dSRichard Lowe 	 */
32810d63b7dSRichard Lowe 	if ((dir->hash.length > 1) || (wcb.get_string()[0] != (int) period_char)) {
32910d63b7dSRichard Lowe 		(void) wcscpy(file_name, wcb.get_string());
33010d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "/");
33110d63b7dSRichard Lowe 		(void) wcscat(file_name, wcs_buffer);
33210d63b7dSRichard Lowe 		file_name_p = file_name + wcslen(file_name);
33310d63b7dSRichard Lowe 	}
33410d63b7dSRichard Lowe 
33510d63b7dSRichard Lowe 	/* Open the directory. */
33610d63b7dSRichard Lowe vpath_loop:
33710d63b7dSRichard Lowe 	dir_fd = opendir(dir->string_mb);
33810d63b7dSRichard Lowe 	if (dir_fd == NULL) {
33910d63b7dSRichard Lowe 		return 0;
34010d63b7dSRichard Lowe 	}
34110d63b7dSRichard Lowe 
34210d63b7dSRichard Lowe 	/* Read all the directory entries. */
34310d63b7dSRichard Lowe 	while ((dp = readdir(dir_fd)) != NULL) {
34410d63b7dSRichard Lowe 		/* We ignore "." and ".." */
34510d63b7dSRichard Lowe 		if ((dp->d_fileno == 0) ||
34610d63b7dSRichard Lowe 		    ((dp->d_name[0] == (int) period_char) &&
34710d63b7dSRichard Lowe 		     ((dp->d_name[1] == 0) ||
34810d63b7dSRichard Lowe 		      ((dp->d_name[1] == (int) period_char) &&
34910d63b7dSRichard Lowe 		       (dp->d_name[2] == 0))))) {
35010d63b7dSRichard Lowe 			continue;
35110d63b7dSRichard Lowe 		}
35210d63b7dSRichard Lowe 		/*
35310d63b7dSRichard Lowe 		 * Build the full name of the file using whatever
35410d63b7dSRichard Lowe 		 * path supplied to the function.
35510d63b7dSRichard Lowe 		 */
35610d63b7dSRichard Lowe 		MBSTOWCS(tmp_wcs_buffer, dp->d_name);
35710d63b7dSRichard Lowe 		(void) wcscpy(file_name_p, tmp_wcs_buffer);
35810d63b7dSRichard Lowe 		file = enter_file_name(file_name, library);
35910d63b7dSRichard Lowe 		if ((pattern != NULL) && amatch(tmp_wcs_buffer, pattern)) {
36010d63b7dSRichard Lowe 			/*
36110d63b7dSRichard Lowe 			 * If we are expanding a wildcard pattern, we
36210d63b7dSRichard Lowe 			 * enter the file as a dependency for the target.
36310d63b7dSRichard Lowe 			 */
36410d63b7dSRichard Lowe 			if (debug_level > 0){
36510d63b7dSRichard Lowe 				WCSTOMBS(mbs_buffer, pattern);
36610d63b7dSRichard Lowe 				(void) printf(gettext("'%s: %s' due to %s expansion\n"),
36710d63b7dSRichard Lowe 					      line->body.line.target->string_mb,
36810d63b7dSRichard Lowe 					      file->string_mb,
36910d63b7dSRichard Lowe 					      mbs_buffer);
37010d63b7dSRichard Lowe 			}
37110d63b7dSRichard Lowe 			enter_dependency(line, file, false);
37210d63b7dSRichard Lowe 			result++;
37310d63b7dSRichard Lowe 		} else {
37410d63b7dSRichard Lowe 			/*
37510d63b7dSRichard Lowe 			 * If the file has an SCCS/s. file,
37610d63b7dSRichard Lowe 			 * we will detect that later on.
37710d63b7dSRichard Lowe 			 */
37810d63b7dSRichard Lowe 			file->stat.has_sccs = NO_SCCS;
37910d63b7dSRichard Lowe 		/*
38010d63b7dSRichard Lowe 		 * If this is an s. file, we also enter it as if it
38110d63b7dSRichard Lowe 		 * existed in the plain directory.
38210d63b7dSRichard Lowe 		 */
38310d63b7dSRichard Lowe 		if ((dp->d_name[0] == 's') &&
38410d63b7dSRichard Lowe 		    (dp->d_name[1] == (int) period_char)) {
38510d63b7dSRichard Lowe 
38610d63b7dSRichard Lowe 			MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
38710d63b7dSRichard Lowe 			plain_file_name_p = plain_file_name;
38810d63b7dSRichard Lowe 			(void) wcscpy(plain_file_name_p, tmp_wcs_buffer);
38910d63b7dSRichard Lowe 			plain_file = GETNAME(plain_file_name, FIND_LENGTH);
39010d63b7dSRichard Lowe 			plain_file->stat.is_file = true;
39110d63b7dSRichard Lowe 			plain_file->stat.has_sccs = HAS_SCCS;
39210d63b7dSRichard Lowe 			/*
39310d63b7dSRichard Lowe 			 * Enter the s. file as a dependency for the
39410d63b7dSRichard Lowe 			 * plain file.
39510d63b7dSRichard Lowe 			 */
39610d63b7dSRichard Lowe 			maybe_append_prop(plain_file, sccs_prop)->
39710d63b7dSRichard Lowe 			  body.sccs.file = file;
39810d63b7dSRichard Lowe 			MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
39910d63b7dSRichard Lowe 			if ((pattern != NULL) &&
40010d63b7dSRichard Lowe 			    amatch(tmp_wcs_buffer, pattern)) {
40110d63b7dSRichard Lowe 				if (debug_level > 0) {
40210d63b7dSRichard Lowe 					WCSTOMBS(mbs_buffer, pattern);
40310d63b7dSRichard Lowe 					(void) printf(gettext("'%s: %s' due to %s expansion\n"),
40410d63b7dSRichard Lowe 						      line->body.line.target->
40510d63b7dSRichard Lowe 						      string_mb,
40610d63b7dSRichard Lowe 						      plain_file->string_mb,
40710d63b7dSRichard Lowe 						      mbs_buffer);
40810d63b7dSRichard Lowe 				}
40910d63b7dSRichard Lowe 				enter_dependency(line, plain_file, false);
41010d63b7dSRichard Lowe 				result++;
41110d63b7dSRichard Lowe 			}
41210d63b7dSRichard Lowe 		}
41310d63b7dSRichard Lowe 	      }
41410d63b7dSRichard Lowe 	}
41510d63b7dSRichard Lowe 	(void) closedir(dir_fd);
41610d63b7dSRichard Lowe 	if ((vpath != NULL) && (*vpath != (int) nul_char)) {
41710d63b7dSRichard Lowe 		while ((*vpath != (int) nul_char) &&
41810d63b7dSRichard Lowe 		       (iswspace(*vpath) || (*vpath == (int) colon_char))) {
41910d63b7dSRichard Lowe 			vpath++;
42010d63b7dSRichard Lowe 		}
42110d63b7dSRichard Lowe 		p = vpath;
42210d63b7dSRichard Lowe 		while ((*vpath != (int) colon_char) &&
42310d63b7dSRichard Lowe 		       (*vpath != (int) nul_char)) {
42410d63b7dSRichard Lowe 			vpath++;
42510d63b7dSRichard Lowe 		}
42610d63b7dSRichard Lowe 		if (vpath > p) {
42710d63b7dSRichard Lowe 			dir = GETNAME(p, vpath - p);
42810d63b7dSRichard Lowe 			goto vpath_loop;
42910d63b7dSRichard Lowe 		}
43010d63b7dSRichard Lowe 	}
43110d63b7dSRichard Lowe /*
43210d63b7dSRichard Lowe  * look into SCCS directory only if it's not svr4. For svr4 dont do that.
43310d63b7dSRichard Lowe  */
43410d63b7dSRichard Lowe 
43510d63b7dSRichard Lowe /*
43610d63b7dSRichard Lowe  * Now read the SCCS directory.
43710d63b7dSRichard Lowe  * Files in the SCSC directory are considered to be part of the set of
43810d63b7dSRichard Lowe  * files in the plain directory. They are also entered in their own right.
43910d63b7dSRichard Lowe  * Prepare the string where we build the true name of the SCCS files.
44010d63b7dSRichard Lowe  */
44110d63b7dSRichard Lowe 	(void) wcsncpy(plain_file_name,
44210d63b7dSRichard Lowe 		      file_name,
44310d63b7dSRichard Lowe 		      file_name_p - file_name);
44410d63b7dSRichard Lowe 	plain_file_name[file_name_p - file_name] = 0;
44510d63b7dSRichard Lowe 	plain_file_name_p = plain_file_name + wcslen(plain_file_name);
44610d63b7dSRichard Lowe 
44710d63b7dSRichard Lowe         if(!svr4) {
44810d63b7dSRichard Lowe 
44910d63b7dSRichard Lowe 	  if (sccs_dir_path != NULL) {
45010d63b7dSRichard Lowe 		wchar_t		tmp_wchar;
45110d63b7dSRichard Lowe 		wchar_t		path[MAXPATHLEN];
45210d63b7dSRichard Lowe 		char		mb_path[MAXPATHLEN];
45310d63b7dSRichard Lowe 
45410d63b7dSRichard Lowe 		if (file_name_p - file_name > 0) {
45510d63b7dSRichard Lowe 			tmp_wchar = *file_name_p;
45610d63b7dSRichard Lowe 			*file_name_p = 0;
45710d63b7dSRichard Lowe 			WCSTOMBS(mbs_buffer, file_name);
45810d63b7dSRichard Lowe 			(void) sprintf(mb_path, "%s/%s/SCCS",
45910d63b7dSRichard Lowe 				        sccs_dir_path,
46010d63b7dSRichard Lowe 				        mbs_buffer);
46110d63b7dSRichard Lowe 			*file_name_p = tmp_wchar;
46210d63b7dSRichard Lowe 		} else {
46310d63b7dSRichard Lowe 			(void) sprintf(mb_path, "%s/SCCS", sccs_dir_path);
46410d63b7dSRichard Lowe 		}
46510d63b7dSRichard Lowe 		MBSTOWCS(path, mb_path);
46610d63b7dSRichard Lowe 		(void) wcscpy(file_name, path);
46710d63b7dSRichard Lowe 	  } else {
46810d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "SCCS");
46910d63b7dSRichard Lowe 		(void) wcscpy(file_name_p, wcs_buffer);
47010d63b7dSRichard Lowe 	  }
47110d63b7dSRichard Lowe 	} else {
47210d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, ".");
47310d63b7dSRichard Lowe 		(void) wcscpy(file_name_p, wcs_buffer);
47410d63b7dSRichard Lowe 	}
47510d63b7dSRichard Lowe 	/* Internalize the constructed SCCS dir name. */
47610d63b7dSRichard Lowe 	(void) exists(dir = GETNAME(file_name, FIND_LENGTH));
47710d63b7dSRichard Lowe 	/* Just give up if the directory file doesnt exist. */
47810d63b7dSRichard Lowe 	if (!dir->stat.is_file) {
47910d63b7dSRichard Lowe 		return result;
48010d63b7dSRichard Lowe 	}
48110d63b7dSRichard Lowe 	/* Open the directory. */
48210d63b7dSRichard Lowe 	dir_fd = opendir(dir->string_mb);
48310d63b7dSRichard Lowe 	if (dir_fd == NULL) {
48410d63b7dSRichard Lowe 		return result;
48510d63b7dSRichard Lowe 	}
48610d63b7dSRichard Lowe 	MBSTOWCS(wcs_buffer, "/");
48710d63b7dSRichard Lowe 	(void) wcscat(file_name, wcs_buffer);
48810d63b7dSRichard Lowe 	file_name_p = file_name + wcslen(file_name);
48910d63b7dSRichard Lowe 
49010d63b7dSRichard Lowe 	while ((dp = readdir(dir_fd)) != NULL) {
49110d63b7dSRichard Lowe 		if ((dp->d_fileno == 0) ||
49210d63b7dSRichard Lowe 		    ((dp->d_name[0] == (int) period_char) &&
49310d63b7dSRichard Lowe 		     ((dp->d_name[1] == 0) ||
49410d63b7dSRichard Lowe 		      ((dp->d_name[1] == (int) period_char) &&
49510d63b7dSRichard Lowe 		       (dp->d_name[2] == 0))))) {
49610d63b7dSRichard Lowe 			continue;
49710d63b7dSRichard Lowe 		}
49810d63b7dSRichard Lowe 		/* Construct and internalize the true name of the SCCS file. */
49910d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, dp->d_name);
50010d63b7dSRichard Lowe 		(void) wcscpy(file_name_p, wcs_buffer);
50110d63b7dSRichard Lowe 		file = GETNAME(file_name, FIND_LENGTH);
50210d63b7dSRichard Lowe 		file->stat.is_file = true;
50310d63b7dSRichard Lowe 		file->stat.has_sccs = NO_SCCS;
50410d63b7dSRichard Lowe 		/*
50510d63b7dSRichard Lowe 		 * If this is an s. file, we also enter it as if it
50610d63b7dSRichard Lowe 		 * existed in the plain directory.
50710d63b7dSRichard Lowe 		 */
50810d63b7dSRichard Lowe 		if ((dp->d_name[0] == 's') &&
50910d63b7dSRichard Lowe 		    (dp->d_name[1] == (int) period_char)) {
51010d63b7dSRichard Lowe 
51110d63b7dSRichard Lowe 			MBSTOWCS(wcs_buffer, dp->d_name + 2);
51210d63b7dSRichard Lowe 			(void) wcscpy(plain_file_name_p, wcs_buffer);
51310d63b7dSRichard Lowe 			plain_file = GETNAME(plain_file_name, FIND_LENGTH);
51410d63b7dSRichard Lowe 			plain_file->stat.is_file = true;
51510d63b7dSRichard Lowe 			plain_file->stat.has_sccs = HAS_SCCS;
51610d63b7dSRichard Lowe 				/* if sccs dependency is already set,skip */
51710d63b7dSRichard Lowe 			if(plain_file->prop) {
51810d63b7dSRichard Lowe 				Property sprop = get_prop(plain_file->prop,sccs_prop);
51910d63b7dSRichard Lowe 				if(sprop != NULL) {
52010d63b7dSRichard Lowe 					if (sprop->body.sccs.file) {
52110d63b7dSRichard Lowe 						goto try_pattern;
52210d63b7dSRichard Lowe 					}
52310d63b7dSRichard Lowe 				}
52410d63b7dSRichard Lowe 			}
52510d63b7dSRichard Lowe 
52610d63b7dSRichard Lowe 			/*
52710d63b7dSRichard Lowe 			 * Enter the s. file as a dependency for the
52810d63b7dSRichard Lowe 			 * plain file.
52910d63b7dSRichard Lowe 			 */
53010d63b7dSRichard Lowe 			maybe_append_prop(plain_file, sccs_prop)->
53110d63b7dSRichard Lowe 			  body.sccs.file = file;
53210d63b7dSRichard Lowe try_pattern:
53310d63b7dSRichard Lowe 			MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
53410d63b7dSRichard Lowe 			if ((pattern != NULL) &&
53510d63b7dSRichard Lowe 			    amatch(tmp_wcs_buffer, pattern)) {
53610d63b7dSRichard Lowe 				if (debug_level > 0) {
53710d63b7dSRichard Lowe 					WCSTOMBS(mbs_buffer, pattern);
53810d63b7dSRichard Lowe 					(void) printf(gettext("'%s: %s' due to %s expansion\n"),
53910d63b7dSRichard Lowe 						      line->body.line.target->
54010d63b7dSRichard Lowe 						      string_mb,
54110d63b7dSRichard Lowe 						      plain_file->string_mb,
54210d63b7dSRichard Lowe 						      mbs_buffer);
54310d63b7dSRichard Lowe 				}
54410d63b7dSRichard Lowe 				enter_dependency(line, plain_file, false);
54510d63b7dSRichard Lowe 				result++;
54610d63b7dSRichard Lowe 			}
54710d63b7dSRichard Lowe 		}
54810d63b7dSRichard Lowe 	}
54910d63b7dSRichard Lowe 	(void) closedir(dir_fd);
55010d63b7dSRichard Lowe 
55110d63b7dSRichard Lowe 	return result;
55210d63b7dSRichard Lowe }
55310d63b7dSRichard Lowe 
55410d63b7dSRichard Lowe /*
55510d63b7dSRichard Lowe  *	enter_file_name(name_string, library)
55610d63b7dSRichard Lowe  *
55710d63b7dSRichard Lowe  *	Helper function for read_dir().
55810d63b7dSRichard Lowe  *
55910d63b7dSRichard Lowe  *	Return value:
56010d63b7dSRichard Lowe  *				The Name that was entered
56110d63b7dSRichard Lowe  *
56210d63b7dSRichard Lowe  *	Parameters:
56310d63b7dSRichard Lowe  *		name_string	Name of the file we want to enter
56410d63b7dSRichard Lowe  *		library		The library it is a member of, if any
56510d63b7dSRichard Lowe  *
56610d63b7dSRichard Lowe  *	Global variables used:
56710d63b7dSRichard Lowe  */
56810d63b7dSRichard Lowe static Name
enter_file_name(wchar_t * name_string,wchar_t * library)56910d63b7dSRichard Lowe enter_file_name(wchar_t *name_string, wchar_t *library)
57010d63b7dSRichard Lowe {
57110d63b7dSRichard Lowe 	wchar_t		buffer[STRING_BUFFER_LENGTH];
57210d63b7dSRichard Lowe 	String_rec	lib_name;
57310d63b7dSRichard Lowe 	Name		name;
57410d63b7dSRichard Lowe 	Property	prop;
57510d63b7dSRichard Lowe 
57610d63b7dSRichard Lowe 	if (library == NULL) {
57710d63b7dSRichard Lowe 		name = GETNAME(name_string, FIND_LENGTH);
57810d63b7dSRichard Lowe 		name->stat.is_file = true;
57910d63b7dSRichard Lowe 		return name;
58010d63b7dSRichard Lowe 	}
58110d63b7dSRichard Lowe 
58210d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(lib_name, buffer);
58310d63b7dSRichard Lowe 	append_string(library, &lib_name, FIND_LENGTH);
58410d63b7dSRichard Lowe 	append_char((int) parenleft_char, &lib_name);
58510d63b7dSRichard Lowe 	append_string(name_string, &lib_name, FIND_LENGTH);
58610d63b7dSRichard Lowe 	append_char((int) parenright_char, &lib_name);
58710d63b7dSRichard Lowe 
58810d63b7dSRichard Lowe 	name = GETNAME(lib_name.buffer.start, FIND_LENGTH);
58910d63b7dSRichard Lowe 	name->stat.is_file = true;
59010d63b7dSRichard Lowe 	name->is_member = true;
59110d63b7dSRichard Lowe 	prop = maybe_append_prop(name, member_prop);
59210d63b7dSRichard Lowe 	prop->body.member.library = GETNAME(library, FIND_LENGTH);
59310d63b7dSRichard Lowe 	prop->body.member.library->stat.is_file = true;
59410d63b7dSRichard Lowe 	prop->body.member.entry = NULL;
59510d63b7dSRichard Lowe 	prop->body.member.member = GETNAME(name_string, FIND_LENGTH);
59610d63b7dSRichard Lowe 	prop->body.member.member->stat.is_file = true;
59710d63b7dSRichard Lowe 	return name;
59810d63b7dSRichard Lowe }
59910d63b7dSRichard Lowe 
60010d63b7dSRichard Lowe /*
60110d63b7dSRichard Lowe  *	star_match(string, pattern)
60210d63b7dSRichard Lowe  *
60310d63b7dSRichard Lowe  *	This is a regular shell type wildcard pattern matcher
60410d63b7dSRichard Lowe  *	It is used when xpanding wildcards in dependency lists
60510d63b7dSRichard Lowe  *
60610d63b7dSRichard Lowe  *	Return value:
60710d63b7dSRichard Lowe  *				Indication if the string matched the pattern
60810d63b7dSRichard Lowe  *
60910d63b7dSRichard Lowe  *	Parameters:
61010d63b7dSRichard Lowe  *		string		String to match
61110d63b7dSRichard Lowe  *		pattern		Pattern to match it against
61210d63b7dSRichard Lowe  *
61310d63b7dSRichard Lowe  *	Global variables used:
61410d63b7dSRichard Lowe  */
61510d63b7dSRichard Lowe static Boolean
star_match(wchar_t * string,wchar_t * pattern)616*e7afc443SToomas Soome star_match(wchar_t *string, wchar_t *pattern)
61710d63b7dSRichard Lowe {
618*e7afc443SToomas Soome 	int		pattern_ch;
61910d63b7dSRichard Lowe 
62010d63b7dSRichard Lowe 	switch (*pattern) {
62110d63b7dSRichard Lowe 	case 0:
62210d63b7dSRichard Lowe 		return succeeded;
62310d63b7dSRichard Lowe 	case bracketleft_char:
62410d63b7dSRichard Lowe 	case question_char:
62510d63b7dSRichard Lowe 	case asterisk_char:
62610d63b7dSRichard Lowe 		while (*string) {
62710d63b7dSRichard Lowe 			if (amatch(string++, pattern)) {
62810d63b7dSRichard Lowe 				return succeeded;
62910d63b7dSRichard Lowe 			}
63010d63b7dSRichard Lowe 		}
63110d63b7dSRichard Lowe 		break;
63210d63b7dSRichard Lowe 	default:
63310d63b7dSRichard Lowe 		pattern_ch = (int) *pattern++;
63410d63b7dSRichard Lowe 		while (*string) {
63510d63b7dSRichard Lowe 			if ((*string++ == pattern_ch) &&
63610d63b7dSRichard Lowe 			    amatch(string, pattern)) {
63710d63b7dSRichard Lowe 				return succeeded;
63810d63b7dSRichard Lowe 			}
63910d63b7dSRichard Lowe 		}
64010d63b7dSRichard Lowe 		break;
64110d63b7dSRichard Lowe 	}
64210d63b7dSRichard Lowe 	return failed;
64310d63b7dSRichard Lowe }
64410d63b7dSRichard Lowe 
64510d63b7dSRichard Lowe /*
64610d63b7dSRichard Lowe  *	amatch(string, pattern)
64710d63b7dSRichard Lowe  *
64810d63b7dSRichard Lowe  *	Helper function for shell pattern matching
64910d63b7dSRichard Lowe  *
65010d63b7dSRichard Lowe  *	Return value:
65110d63b7dSRichard Lowe  *				Indication if the string matched the pattern
65210d63b7dSRichard Lowe  *
65310d63b7dSRichard Lowe  *	Parameters:
65410d63b7dSRichard Lowe  *		string		String to match
65510d63b7dSRichard Lowe  *		pattern		Pattern to match it against
65610d63b7dSRichard Lowe  *
65710d63b7dSRichard Lowe  *	Global variables used:
65810d63b7dSRichard Lowe  */
65910d63b7dSRichard Lowe static Boolean
amatch(wchar_t * string,wchar_t * pattern)660*e7afc443SToomas Soome amatch(wchar_t *string, wchar_t *pattern)
66110d63b7dSRichard Lowe {
662*e7afc443SToomas Soome 	long		lower_bound;
663*e7afc443SToomas Soome 	long		string_ch;
664*e7afc443SToomas Soome 	long		pattern_ch;
665*e7afc443SToomas Soome 	int		k;
66610d63b7dSRichard Lowe 
66710d63b7dSRichard Lowe top:
66810d63b7dSRichard Lowe 	for (; 1; pattern++, string++) {
66910d63b7dSRichard Lowe 		lower_bound = 017777777777;
67010d63b7dSRichard Lowe 		string_ch = *string;
67110d63b7dSRichard Lowe 		switch (pattern_ch = *pattern) {
67210d63b7dSRichard Lowe 		case bracketleft_char:
67310d63b7dSRichard Lowe 			k = 0;
67410d63b7dSRichard Lowe 			while ((pattern_ch = *++pattern) != 0) {
67510d63b7dSRichard Lowe 				switch (pattern_ch) {
67610d63b7dSRichard Lowe 				case bracketright_char:
67710d63b7dSRichard Lowe 					if (!k) {
67810d63b7dSRichard Lowe 						return failed;
67910d63b7dSRichard Lowe 					}
68010d63b7dSRichard Lowe 					string++;
68110d63b7dSRichard Lowe 					pattern++;
68210d63b7dSRichard Lowe 					goto top;
68310d63b7dSRichard Lowe 				case hyphen_char:
68410d63b7dSRichard Lowe 					k |= (lower_bound <= string_ch) &&
68510d63b7dSRichard Lowe 					     (string_ch <=
68610d63b7dSRichard Lowe 					      (pattern_ch = pattern[1]));
6878e0c8248SAndrew Stormont 					/* FALLTHROUGH */
68810d63b7dSRichard Lowe 				default:
68910d63b7dSRichard Lowe 					if (string_ch ==
69010d63b7dSRichard Lowe 					    (lower_bound = pattern_ch)) {
69110d63b7dSRichard Lowe 						k++;
69210d63b7dSRichard Lowe 					}
69310d63b7dSRichard Lowe 				}
69410d63b7dSRichard Lowe 			}
69510d63b7dSRichard Lowe 			return failed;
69610d63b7dSRichard Lowe 		case asterisk_char:
69710d63b7dSRichard Lowe 			return star_match(string, ++pattern);
69810d63b7dSRichard Lowe 		case 0:
69910d63b7dSRichard Lowe 			return BOOLEAN(!string_ch);
70010d63b7dSRichard Lowe 		case question_char:
70110d63b7dSRichard Lowe 			if (string_ch == 0) {
70210d63b7dSRichard Lowe 				return failed;
70310d63b7dSRichard Lowe 			}
70410d63b7dSRichard Lowe 			break;
70510d63b7dSRichard Lowe 		default:
70610d63b7dSRichard Lowe 			if (pattern_ch != string_ch) {
70710d63b7dSRichard Lowe 				return failed;
70810d63b7dSRichard Lowe 			}
70910d63b7dSRichard Lowe 			break;
71010d63b7dSRichard Lowe 		}
71110d63b7dSRichard Lowe 	}
71210d63b7dSRichard Lowe 	/* NOTREACHED */
71310d63b7dSRichard Lowe }
71410d63b7dSRichard Lowe 
715