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