1*10d63b7dSRichard Lowe /*
2*10d63b7dSRichard Lowe * CDDL HEADER START
3*10d63b7dSRichard Lowe *
4*10d63b7dSRichard Lowe * The contents of this file are subject to the terms of the
5*10d63b7dSRichard Lowe * Common Development and Distribution License (the "License").
6*10d63b7dSRichard Lowe * You may not use this file except in compliance with the License.
7*10d63b7dSRichard Lowe *
8*10d63b7dSRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10d63b7dSRichard Lowe * or http://www.opensolaris.org/os/licensing.
10*10d63b7dSRichard Lowe * See the License for the specific language governing permissions
11*10d63b7dSRichard Lowe * and limitations under the License.
12*10d63b7dSRichard Lowe *
13*10d63b7dSRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
14*10d63b7dSRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10d63b7dSRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
16*10d63b7dSRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
17*10d63b7dSRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
18*10d63b7dSRichard Lowe *
19*10d63b7dSRichard Lowe * CDDL HEADER END
20*10d63b7dSRichard Lowe */
21*10d63b7dSRichard Lowe /*
22*10d63b7dSRichard Lowe * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
23*10d63b7dSRichard Lowe * Use is subject to license terms.
24*10d63b7dSRichard Lowe */
25*10d63b7dSRichard Lowe
26*10d63b7dSRichard Lowe /*
27*10d63b7dSRichard Lowe * files.c
28*10d63b7dSRichard Lowe *
29*10d63b7dSRichard Lowe * Various file related routines:
30*10d63b7dSRichard Lowe * Figure out if file exists
31*10d63b7dSRichard Lowe * Wildcard resolution for directory reader
32*10d63b7dSRichard Lowe * Directory reader
33*10d63b7dSRichard Lowe */
34*10d63b7dSRichard Lowe
35*10d63b7dSRichard Lowe
36*10d63b7dSRichard Lowe /*
37*10d63b7dSRichard Lowe * Included files
38*10d63b7dSRichard Lowe */
39*10d63b7dSRichard Lowe #include <dirent.h> /* opendir() */
40*10d63b7dSRichard Lowe #include <errno.h> /* errno */
41*10d63b7dSRichard Lowe #include <mk/defs.h>
42*10d63b7dSRichard Lowe #include <mksh/macro.h> /* getvar() */
43*10d63b7dSRichard Lowe #include <mksh/misc.h> /* get_prop(), append_prop() */
44*10d63b7dSRichard Lowe #include <sys/stat.h> /* lstat() */
45*10d63b7dSRichard Lowe #include <libintl.h>
46*10d63b7dSRichard Lowe
47*10d63b7dSRichard Lowe /*
48*10d63b7dSRichard Lowe * Defined macros
49*10d63b7dSRichard Lowe */
50*10d63b7dSRichard Lowe
51*10d63b7dSRichard Lowe /*
52*10d63b7dSRichard Lowe * typedefs & structs
53*10d63b7dSRichard Lowe */
54*10d63b7dSRichard Lowe
55*10d63b7dSRichard Lowe /*
56*10d63b7dSRichard Lowe * Static variables
57*10d63b7dSRichard Lowe */
58*10d63b7dSRichard Lowe
59*10d63b7dSRichard Lowe /*
60*10d63b7dSRichard Lowe * File table of contents
61*10d63b7dSRichard Lowe */
62*10d63b7dSRichard Lowe extern timestruc_t& exists(register Name target);
63*10d63b7dSRichard Lowe extern void set_target_stat(register Name target, struct stat buf);
64*10d63b7dSRichard Lowe static timestruc_t& vpath_exists(register Name target);
65*10d63b7dSRichard Lowe static Name enter_file_name(wchar_t *name_string, wchar_t *library);
66*10d63b7dSRichard Lowe static Boolean star_match(register char *string, register char *pattern);
67*10d63b7dSRichard Lowe static Boolean amatch(register wchar_t *string, register wchar_t *pattern);
68*10d63b7dSRichard Lowe
69*10d63b7dSRichard Lowe /*
70*10d63b7dSRichard Lowe * exists(target)
71*10d63b7dSRichard Lowe *
72*10d63b7dSRichard Lowe * Figure out the timestamp for one target.
73*10d63b7dSRichard Lowe *
74*10d63b7dSRichard Lowe * Return value:
75*10d63b7dSRichard Lowe * The time the target was created
76*10d63b7dSRichard Lowe *
77*10d63b7dSRichard Lowe * Parameters:
78*10d63b7dSRichard Lowe * target The target to check
79*10d63b7dSRichard Lowe *
80*10d63b7dSRichard Lowe * Global variables used:
81*10d63b7dSRichard Lowe * debug_level Should we trace the stat call?
82*10d63b7dSRichard Lowe * recursion_level Used for tracing
83*10d63b7dSRichard Lowe * vpath_defined Was the variable VPATH defined in environment?
84*10d63b7dSRichard Lowe */
85*10d63b7dSRichard Lowe timestruc_t&
exists(register Name target)86*10d63b7dSRichard Lowe exists(register Name target)
87*10d63b7dSRichard Lowe {
88*10d63b7dSRichard Lowe struct stat buf;
89*10d63b7dSRichard Lowe register int result;
90*10d63b7dSRichard Lowe
91*10d63b7dSRichard Lowe /* We cache stat information. */
92*10d63b7dSRichard Lowe if (target->stat.time != file_no_time) {
93*10d63b7dSRichard Lowe return target->stat.time;
94*10d63b7dSRichard Lowe }
95*10d63b7dSRichard Lowe
96*10d63b7dSRichard Lowe /*
97*10d63b7dSRichard Lowe * If the target is a member, we have to extract the time
98*10d63b7dSRichard Lowe * from the archive.
99*10d63b7dSRichard Lowe */
100*10d63b7dSRichard Lowe if (target->is_member &&
101*10d63b7dSRichard Lowe (get_prop(target->prop, member_prop) != NULL)) {
102*10d63b7dSRichard Lowe return read_archive(target);
103*10d63b7dSRichard Lowe }
104*10d63b7dSRichard Lowe
105*10d63b7dSRichard Lowe if (debug_level > 1) {
106*10d63b7dSRichard Lowe (void) printf("%*sstat(%s)\n",
107*10d63b7dSRichard Lowe recursion_level,
108*10d63b7dSRichard Lowe "",
109*10d63b7dSRichard Lowe target->string_mb);
110*10d63b7dSRichard Lowe }
111*10d63b7dSRichard Lowe
112*10d63b7dSRichard Lowe result = lstat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT);
113*10d63b7dSRichard Lowe if ((result != -1) && ((buf.st_mode & S_IFMT) == S_IFLNK)) {
114*10d63b7dSRichard Lowe /*
115*10d63b7dSRichard Lowe * If the file is a symbolic link, we remember that
116*10d63b7dSRichard Lowe * and then we get the status for the refd file.
117*10d63b7dSRichard Lowe */
118*10d63b7dSRichard Lowe target->stat.is_sym_link = true;
119*10d63b7dSRichard Lowe result = stat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT);
120*10d63b7dSRichard Lowe } else {
121*10d63b7dSRichard Lowe target->stat.is_sym_link = false;
122*10d63b7dSRichard Lowe }
123*10d63b7dSRichard Lowe
124*10d63b7dSRichard Lowe if (result < 0) {
125*10d63b7dSRichard Lowe target->stat.time = file_doesnt_exist;
126*10d63b7dSRichard Lowe target->stat.stat_errno = errno;
127*10d63b7dSRichard Lowe if ((errno == ENOENT) &&
128*10d63b7dSRichard Lowe vpath_defined &&
129*10d63b7dSRichard Lowe /* azv, fixing bug 1262942, VPATH works with a leaf name
130*10d63b7dSRichard Lowe * but not a directory name.
131*10d63b7dSRichard Lowe */
132*10d63b7dSRichard Lowe (target->string_mb[0] != (int) slash_char) ) {
133*10d63b7dSRichard Lowe /* BID_1214655 */
134*10d63b7dSRichard Lowe /* azv */
135*10d63b7dSRichard Lowe vpath_exists(target);
136*10d63b7dSRichard Lowe // return vpath_exists(target);
137*10d63b7dSRichard Lowe }
138*10d63b7dSRichard Lowe } else {
139*10d63b7dSRichard Lowe /* Save all the information we need about the file */
140*10d63b7dSRichard Lowe target->stat.stat_errno = 0;
141*10d63b7dSRichard Lowe target->stat.is_file = true;
142*10d63b7dSRichard Lowe target->stat.mode = buf.st_mode & 0777;
143*10d63b7dSRichard Lowe target->stat.size = buf.st_size;
144*10d63b7dSRichard Lowe target->stat.is_dir =
145*10d63b7dSRichard Lowe BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR);
146*10d63b7dSRichard Lowe if (target->stat.is_dir) {
147*10d63b7dSRichard Lowe target->stat.time = file_is_dir;
148*10d63b7dSRichard Lowe } else {
149*10d63b7dSRichard Lowe /* target->stat.time = buf.st_mtime; */
150*10d63b7dSRichard Lowe /* BID_1129806 */
151*10d63b7dSRichard Lowe /* vis@nbsp.nsk.su */
152*10d63b7dSRichard Lowe target->stat.time = MAX(buf.st_mtim, file_min_time);
153*10d63b7dSRichard Lowe }
154*10d63b7dSRichard Lowe }
155*10d63b7dSRichard Lowe if ((target->colon_splits > 0) &&
156*10d63b7dSRichard Lowe (get_prop(target->prop, time_prop) == NULL)) {
157*10d63b7dSRichard Lowe append_prop(target, time_prop)->body.time.time =
158*10d63b7dSRichard Lowe target->stat.time;
159*10d63b7dSRichard Lowe }
160*10d63b7dSRichard Lowe return target->stat.time;
161*10d63b7dSRichard Lowe }
162*10d63b7dSRichard Lowe
163*10d63b7dSRichard Lowe /*
164*10d63b7dSRichard Lowe * set_target_stat( target, buf)
165*10d63b7dSRichard Lowe *
166*10d63b7dSRichard Lowe * Called by exists() to set some stat fields in the Name structure
167*10d63b7dSRichard Lowe * to those read by the stat_vroot() call (from disk).
168*10d63b7dSRichard Lowe *
169*10d63b7dSRichard Lowe * Parameters:
170*10d63b7dSRichard Lowe * target The target whose stat field is set
171*10d63b7dSRichard Lowe * buf stat values (on disk) of the file
172*10d63b7dSRichard Lowe * represented by target.
173*10d63b7dSRichard Lowe */
174*10d63b7dSRichard Lowe void
set_target_stat(register Name target,struct stat buf)175*10d63b7dSRichard Lowe set_target_stat(register Name target, struct stat buf)
176*10d63b7dSRichard Lowe {
177*10d63b7dSRichard Lowe target->stat.stat_errno = 0;
178*10d63b7dSRichard Lowe target->stat.is_file = true;
179*10d63b7dSRichard Lowe target->stat.mode = buf.st_mode & 0777;
180*10d63b7dSRichard Lowe target->stat.size = buf.st_size;
181*10d63b7dSRichard Lowe target->stat.is_dir =
182*10d63b7dSRichard Lowe BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR);
183*10d63b7dSRichard Lowe if (target->stat.is_dir) {
184*10d63b7dSRichard Lowe target->stat.time = file_is_dir;
185*10d63b7dSRichard Lowe } else {
186*10d63b7dSRichard Lowe /* target->stat.time = buf.st_mtime; */
187*10d63b7dSRichard Lowe /* BID_1129806 */
188*10d63b7dSRichard Lowe /* vis@nbsp.nsk.su */
189*10d63b7dSRichard Lowe target->stat.time = MAX(buf.st_mtim, file_min_time);
190*10d63b7dSRichard Lowe }
191*10d63b7dSRichard Lowe }
192*10d63b7dSRichard Lowe
193*10d63b7dSRichard Lowe
194*10d63b7dSRichard Lowe /*
195*10d63b7dSRichard Lowe * vpath_exists(target)
196*10d63b7dSRichard Lowe *
197*10d63b7dSRichard Lowe * Called if exists() discovers that there is a VPATH defined.
198*10d63b7dSRichard Lowe * This function stats the VPATH translation of the target.
199*10d63b7dSRichard Lowe *
200*10d63b7dSRichard Lowe * Return value:
201*10d63b7dSRichard Lowe * The time the target was created
202*10d63b7dSRichard Lowe *
203*10d63b7dSRichard Lowe * Parameters:
204*10d63b7dSRichard Lowe * target The target to check
205*10d63b7dSRichard Lowe *
206*10d63b7dSRichard Lowe * Global variables used:
207*10d63b7dSRichard Lowe * vpath_name The Name "VPATH", used to get macro value
208*10d63b7dSRichard Lowe */
209*10d63b7dSRichard Lowe static timestruc_t&
vpath_exists(register Name target)210*10d63b7dSRichard Lowe vpath_exists(register Name target)
211*10d63b7dSRichard Lowe {
212*10d63b7dSRichard Lowe wchar_t *vpath;
213*10d63b7dSRichard Lowe wchar_t file_name[MAXPATHLEN];
214*10d63b7dSRichard Lowe wchar_t *name_p;
215*10d63b7dSRichard Lowe Name alias;
216*10d63b7dSRichard Lowe
217*10d63b7dSRichard Lowe /*
218*10d63b7dSRichard Lowe * To avoid recursive search through VPATH when exists(alias) is called
219*10d63b7dSRichard Lowe */
220*10d63b7dSRichard Lowe vpath_defined = false;
221*10d63b7dSRichard Lowe
222*10d63b7dSRichard Lowe Wstring wcb(getvar(vpath_name));
223*10d63b7dSRichard Lowe Wstring wcb1(target);
224*10d63b7dSRichard Lowe
225*10d63b7dSRichard Lowe vpath = wcb.get_string();
226*10d63b7dSRichard Lowe
227*10d63b7dSRichard Lowe while (*vpath != (int) nul_char) {
228*10d63b7dSRichard Lowe name_p = file_name;
229*10d63b7dSRichard Lowe while ((*vpath != (int) colon_char) &&
230*10d63b7dSRichard Lowe (*vpath != (int) nul_char)) {
231*10d63b7dSRichard Lowe *name_p++ = *vpath++;
232*10d63b7dSRichard Lowe }
233*10d63b7dSRichard Lowe *name_p++ = (int) slash_char;
234*10d63b7dSRichard Lowe (void) wcscpy(name_p, wcb1.get_string());
235*10d63b7dSRichard Lowe alias = GETNAME(file_name, FIND_LENGTH);
236*10d63b7dSRichard Lowe if (exists(alias) != file_doesnt_exist) {
237*10d63b7dSRichard Lowe target->stat.is_file = true;
238*10d63b7dSRichard Lowe target->stat.mode = alias->stat.mode;
239*10d63b7dSRichard Lowe target->stat.size = alias->stat.size;
240*10d63b7dSRichard Lowe target->stat.is_dir = alias->stat.is_dir;
241*10d63b7dSRichard Lowe target->stat.time = alias->stat.time;
242*10d63b7dSRichard Lowe maybe_append_prop(target, vpath_alias_prop)->
243*10d63b7dSRichard Lowe body.vpath_alias.alias = alias;
244*10d63b7dSRichard Lowe target->has_vpath_alias_prop = true;
245*10d63b7dSRichard Lowe vpath_defined = true;
246*10d63b7dSRichard Lowe return alias->stat.time;
247*10d63b7dSRichard Lowe }
248*10d63b7dSRichard Lowe while ((*vpath != (int) nul_char) &&
249*10d63b7dSRichard Lowe ((*vpath == (int) colon_char) || iswspace(*vpath))) {
250*10d63b7dSRichard Lowe vpath++;
251*10d63b7dSRichard Lowe }
252*10d63b7dSRichard Lowe }
253*10d63b7dSRichard Lowe /*
254*10d63b7dSRichard Lowe * Restore vpath_defined
255*10d63b7dSRichard Lowe */
256*10d63b7dSRichard Lowe vpath_defined = true;
257*10d63b7dSRichard Lowe return target->stat.time;
258*10d63b7dSRichard Lowe }
259*10d63b7dSRichard Lowe
260*10d63b7dSRichard Lowe /*
261*10d63b7dSRichard Lowe * read_dir(dir, pattern, line, library)
262*10d63b7dSRichard Lowe *
263*10d63b7dSRichard Lowe * Used to enter the contents of directories into makes namespace.
264*10d63b7dSRichard Lowe * Presence of a file is important when scanning for implicit rules.
265*10d63b7dSRichard Lowe * read_dir() is also used to expand wildcards in dependency lists.
266*10d63b7dSRichard Lowe *
267*10d63b7dSRichard Lowe * Return value:
268*10d63b7dSRichard Lowe * Non-0 if we found files to match the pattern
269*10d63b7dSRichard Lowe *
270*10d63b7dSRichard Lowe * Parameters:
271*10d63b7dSRichard Lowe * dir Path to the directory to read
272*10d63b7dSRichard Lowe * pattern Pattern for that files should match or NULL
273*10d63b7dSRichard Lowe * line When we scan using a pattern we enter files
274*10d63b7dSRichard Lowe * we find as dependencies for this line
275*10d63b7dSRichard Lowe * library If we scan for "lib.a(<wildcard-member>)"
276*10d63b7dSRichard Lowe *
277*10d63b7dSRichard Lowe * Global variables used:
278*10d63b7dSRichard Lowe * debug_level Should we trace the dir reading?
279*10d63b7dSRichard Lowe * dot The Name ".", compared against
280*10d63b7dSRichard Lowe * sccs_dir_path The path to the SCCS dir (from PROJECTDIR)
281*10d63b7dSRichard Lowe * vpath_defined Was the variable VPATH defined in environment?
282*10d63b7dSRichard Lowe * vpath_name The Name "VPATH", use to get macro value
283*10d63b7dSRichard Lowe */
284*10d63b7dSRichard Lowe int
read_dir(Name dir,wchar_t * pattern,Property line,wchar_t * library)285*10d63b7dSRichard Lowe read_dir(Name dir, wchar_t *pattern, Property line, wchar_t *library)
286*10d63b7dSRichard Lowe {
287*10d63b7dSRichard Lowe wchar_t file_name[MAXPATHLEN];
288*10d63b7dSRichard Lowe wchar_t *file_name_p = file_name;
289*10d63b7dSRichard Lowe Name file;
290*10d63b7dSRichard Lowe wchar_t plain_file_name[MAXPATHLEN];
291*10d63b7dSRichard Lowe wchar_t *plain_file_name_p;
292*10d63b7dSRichard Lowe Name plain_file;
293*10d63b7dSRichard Lowe wchar_t tmp_wcs_buffer[MAXPATHLEN];
294*10d63b7dSRichard Lowe DIR *dir_fd;
295*10d63b7dSRichard Lowe int m_local_dependency=0;
296*10d63b7dSRichard Lowe #define d_fileno d_ino
297*10d63b7dSRichard Lowe register struct dirent *dp;
298*10d63b7dSRichard Lowe wchar_t *vpath = NULL;
299*10d63b7dSRichard Lowe wchar_t *p;
300*10d63b7dSRichard Lowe int result = 0;
301*10d63b7dSRichard Lowe
302*10d63b7dSRichard Lowe if(dir->hash.length >= MAXPATHLEN) {
303*10d63b7dSRichard Lowe return 0;
304*10d63b7dSRichard Lowe }
305*10d63b7dSRichard Lowe
306*10d63b7dSRichard Lowe Wstring wcb(dir);
307*10d63b7dSRichard Lowe Wstring vps;
308*10d63b7dSRichard Lowe
309*10d63b7dSRichard Lowe /* A directory is only read once unless we need to expand wildcards. */
310*10d63b7dSRichard Lowe if (pattern == NULL) {
311*10d63b7dSRichard Lowe if (dir->has_read_dir) {
312*10d63b7dSRichard Lowe return 0;
313*10d63b7dSRichard Lowe }
314*10d63b7dSRichard Lowe dir->has_read_dir = true;
315*10d63b7dSRichard Lowe }
316*10d63b7dSRichard Lowe /* Check if VPATH is active and setup list if it is. */
317*10d63b7dSRichard Lowe if (vpath_defined && (dir == dot)) {
318*10d63b7dSRichard Lowe vps.init(getvar(vpath_name));
319*10d63b7dSRichard Lowe vpath = vps.get_string();
320*10d63b7dSRichard Lowe }
321*10d63b7dSRichard Lowe
322*10d63b7dSRichard Lowe /*
323*10d63b7dSRichard Lowe * Prepare the string where we build the full name of the
324*10d63b7dSRichard Lowe * files in the directory.
325*10d63b7dSRichard Lowe */
326*10d63b7dSRichard Lowe if ((dir->hash.length > 1) || (wcb.get_string()[0] != (int) period_char)) {
327*10d63b7dSRichard Lowe (void) wcscpy(file_name, wcb.get_string());
328*10d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, "/");
329*10d63b7dSRichard Lowe (void) wcscat(file_name, wcs_buffer);
330*10d63b7dSRichard Lowe file_name_p = file_name + wcslen(file_name);
331*10d63b7dSRichard Lowe }
332*10d63b7dSRichard Lowe
333*10d63b7dSRichard Lowe /* Open the directory. */
334*10d63b7dSRichard Lowe vpath_loop:
335*10d63b7dSRichard Lowe dir_fd = opendir(dir->string_mb);
336*10d63b7dSRichard Lowe if (dir_fd == NULL) {
337*10d63b7dSRichard Lowe return 0;
338*10d63b7dSRichard Lowe }
339*10d63b7dSRichard Lowe
340*10d63b7dSRichard Lowe /* Read all the directory entries. */
341*10d63b7dSRichard Lowe while ((dp = readdir(dir_fd)) != NULL) {
342*10d63b7dSRichard Lowe /* We ignore "." and ".." */
343*10d63b7dSRichard Lowe if ((dp->d_fileno == 0) ||
344*10d63b7dSRichard Lowe ((dp->d_name[0] == (int) period_char) &&
345*10d63b7dSRichard Lowe ((dp->d_name[1] == 0) ||
346*10d63b7dSRichard Lowe ((dp->d_name[1] == (int) period_char) &&
347*10d63b7dSRichard Lowe (dp->d_name[2] == 0))))) {
348*10d63b7dSRichard Lowe continue;
349*10d63b7dSRichard Lowe }
350*10d63b7dSRichard Lowe /*
351*10d63b7dSRichard Lowe * Build the full name of the file using whatever
352*10d63b7dSRichard Lowe * path supplied to the function.
353*10d63b7dSRichard Lowe */
354*10d63b7dSRichard Lowe MBSTOWCS(tmp_wcs_buffer, dp->d_name);
355*10d63b7dSRichard Lowe (void) wcscpy(file_name_p, tmp_wcs_buffer);
356*10d63b7dSRichard Lowe file = enter_file_name(file_name, library);
357*10d63b7dSRichard Lowe if ((pattern != NULL) && amatch(tmp_wcs_buffer, pattern)) {
358*10d63b7dSRichard Lowe /*
359*10d63b7dSRichard Lowe * If we are expanding a wildcard pattern, we
360*10d63b7dSRichard Lowe * enter the file as a dependency for the target.
361*10d63b7dSRichard Lowe */
362*10d63b7dSRichard Lowe if (debug_level > 0){
363*10d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, pattern);
364*10d63b7dSRichard Lowe (void) printf(gettext("'%s: %s' due to %s expansion\n"),
365*10d63b7dSRichard Lowe line->body.line.target->string_mb,
366*10d63b7dSRichard Lowe file->string_mb,
367*10d63b7dSRichard Lowe mbs_buffer);
368*10d63b7dSRichard Lowe }
369*10d63b7dSRichard Lowe enter_dependency(line, file, false);
370*10d63b7dSRichard Lowe result++;
371*10d63b7dSRichard Lowe } else {
372*10d63b7dSRichard Lowe /*
373*10d63b7dSRichard Lowe * If the file has an SCCS/s. file,
374*10d63b7dSRichard Lowe * we will detect that later on.
375*10d63b7dSRichard Lowe */
376*10d63b7dSRichard Lowe file->stat.has_sccs = NO_SCCS;
377*10d63b7dSRichard Lowe /*
378*10d63b7dSRichard Lowe * If this is an s. file, we also enter it as if it
379*10d63b7dSRichard Lowe * existed in the plain directory.
380*10d63b7dSRichard Lowe */
381*10d63b7dSRichard Lowe if ((dp->d_name[0] == 's') &&
382*10d63b7dSRichard Lowe (dp->d_name[1] == (int) period_char)) {
383*10d63b7dSRichard Lowe
384*10d63b7dSRichard Lowe MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
385*10d63b7dSRichard Lowe plain_file_name_p = plain_file_name;
386*10d63b7dSRichard Lowe (void) wcscpy(plain_file_name_p, tmp_wcs_buffer);
387*10d63b7dSRichard Lowe plain_file = GETNAME(plain_file_name, FIND_LENGTH);
388*10d63b7dSRichard Lowe plain_file->stat.is_file = true;
389*10d63b7dSRichard Lowe plain_file->stat.has_sccs = HAS_SCCS;
390*10d63b7dSRichard Lowe /*
391*10d63b7dSRichard Lowe * Enter the s. file as a dependency for the
392*10d63b7dSRichard Lowe * plain file.
393*10d63b7dSRichard Lowe */
394*10d63b7dSRichard Lowe maybe_append_prop(plain_file, sccs_prop)->
395*10d63b7dSRichard Lowe body.sccs.file = file;
396*10d63b7dSRichard Lowe MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
397*10d63b7dSRichard Lowe if ((pattern != NULL) &&
398*10d63b7dSRichard Lowe amatch(tmp_wcs_buffer, pattern)) {
399*10d63b7dSRichard Lowe if (debug_level > 0) {
400*10d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, pattern);
401*10d63b7dSRichard Lowe (void) printf(gettext("'%s: %s' due to %s expansion\n"),
402*10d63b7dSRichard Lowe line->body.line.target->
403*10d63b7dSRichard Lowe string_mb,
404*10d63b7dSRichard Lowe plain_file->string_mb,
405*10d63b7dSRichard Lowe mbs_buffer);
406*10d63b7dSRichard Lowe }
407*10d63b7dSRichard Lowe enter_dependency(line, plain_file, false);
408*10d63b7dSRichard Lowe result++;
409*10d63b7dSRichard Lowe }
410*10d63b7dSRichard Lowe }
411*10d63b7dSRichard Lowe }
412*10d63b7dSRichard Lowe }
413*10d63b7dSRichard Lowe (void) closedir(dir_fd);
414*10d63b7dSRichard Lowe if ((vpath != NULL) && (*vpath != (int) nul_char)) {
415*10d63b7dSRichard Lowe while ((*vpath != (int) nul_char) &&
416*10d63b7dSRichard Lowe (iswspace(*vpath) || (*vpath == (int) colon_char))) {
417*10d63b7dSRichard Lowe vpath++;
418*10d63b7dSRichard Lowe }
419*10d63b7dSRichard Lowe p = vpath;
420*10d63b7dSRichard Lowe while ((*vpath != (int) colon_char) &&
421*10d63b7dSRichard Lowe (*vpath != (int) nul_char)) {
422*10d63b7dSRichard Lowe vpath++;
423*10d63b7dSRichard Lowe }
424*10d63b7dSRichard Lowe if (vpath > p) {
425*10d63b7dSRichard Lowe dir = GETNAME(p, vpath - p);
426*10d63b7dSRichard Lowe goto vpath_loop;
427*10d63b7dSRichard Lowe }
428*10d63b7dSRichard Lowe }
429*10d63b7dSRichard Lowe /*
430*10d63b7dSRichard Lowe * look into SCCS directory only if it's not svr4. For svr4 dont do that.
431*10d63b7dSRichard Lowe */
432*10d63b7dSRichard Lowe
433*10d63b7dSRichard Lowe /*
434*10d63b7dSRichard Lowe * Now read the SCCS directory.
435*10d63b7dSRichard Lowe * Files in the SCSC directory are considered to be part of the set of
436*10d63b7dSRichard Lowe * files in the plain directory. They are also entered in their own right.
437*10d63b7dSRichard Lowe * Prepare the string where we build the true name of the SCCS files.
438*10d63b7dSRichard Lowe */
439*10d63b7dSRichard Lowe (void) wcsncpy(plain_file_name,
440*10d63b7dSRichard Lowe file_name,
441*10d63b7dSRichard Lowe file_name_p - file_name);
442*10d63b7dSRichard Lowe plain_file_name[file_name_p - file_name] = 0;
443*10d63b7dSRichard Lowe plain_file_name_p = plain_file_name + wcslen(plain_file_name);
444*10d63b7dSRichard Lowe
445*10d63b7dSRichard Lowe if(!svr4) {
446*10d63b7dSRichard Lowe
447*10d63b7dSRichard Lowe if (sccs_dir_path != NULL) {
448*10d63b7dSRichard Lowe wchar_t tmp_wchar;
449*10d63b7dSRichard Lowe wchar_t path[MAXPATHLEN];
450*10d63b7dSRichard Lowe char mb_path[MAXPATHLEN];
451*10d63b7dSRichard Lowe
452*10d63b7dSRichard Lowe if (file_name_p - file_name > 0) {
453*10d63b7dSRichard Lowe tmp_wchar = *file_name_p;
454*10d63b7dSRichard Lowe *file_name_p = 0;
455*10d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, file_name);
456*10d63b7dSRichard Lowe (void) sprintf(mb_path, "%s/%s/SCCS",
457*10d63b7dSRichard Lowe sccs_dir_path,
458*10d63b7dSRichard Lowe mbs_buffer);
459*10d63b7dSRichard Lowe *file_name_p = tmp_wchar;
460*10d63b7dSRichard Lowe } else {
461*10d63b7dSRichard Lowe (void) sprintf(mb_path, "%s/SCCS", sccs_dir_path);
462*10d63b7dSRichard Lowe }
463*10d63b7dSRichard Lowe MBSTOWCS(path, mb_path);
464*10d63b7dSRichard Lowe (void) wcscpy(file_name, path);
465*10d63b7dSRichard Lowe } else {
466*10d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, "SCCS");
467*10d63b7dSRichard Lowe (void) wcscpy(file_name_p, wcs_buffer);
468*10d63b7dSRichard Lowe }
469*10d63b7dSRichard Lowe } else {
470*10d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, ".");
471*10d63b7dSRichard Lowe (void) wcscpy(file_name_p, wcs_buffer);
472*10d63b7dSRichard Lowe }
473*10d63b7dSRichard Lowe /* Internalize the constructed SCCS dir name. */
474*10d63b7dSRichard Lowe (void) exists(dir = GETNAME(file_name, FIND_LENGTH));
475*10d63b7dSRichard Lowe /* Just give up if the directory file doesnt exist. */
476*10d63b7dSRichard Lowe if (!dir->stat.is_file) {
477*10d63b7dSRichard Lowe return result;
478*10d63b7dSRichard Lowe }
479*10d63b7dSRichard Lowe /* Open the directory. */
480*10d63b7dSRichard Lowe dir_fd = opendir(dir->string_mb);
481*10d63b7dSRichard Lowe if (dir_fd == NULL) {
482*10d63b7dSRichard Lowe return result;
483*10d63b7dSRichard Lowe }
484*10d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, "/");
485*10d63b7dSRichard Lowe (void) wcscat(file_name, wcs_buffer);
486*10d63b7dSRichard Lowe file_name_p = file_name + wcslen(file_name);
487*10d63b7dSRichard Lowe
488*10d63b7dSRichard Lowe while ((dp = readdir(dir_fd)) != NULL) {
489*10d63b7dSRichard Lowe if ((dp->d_fileno == 0) ||
490*10d63b7dSRichard Lowe ((dp->d_name[0] == (int) period_char) &&
491*10d63b7dSRichard Lowe ((dp->d_name[1] == 0) ||
492*10d63b7dSRichard Lowe ((dp->d_name[1] == (int) period_char) &&
493*10d63b7dSRichard Lowe (dp->d_name[2] == 0))))) {
494*10d63b7dSRichard Lowe continue;
495*10d63b7dSRichard Lowe }
496*10d63b7dSRichard Lowe /* Construct and internalize the true name of the SCCS file. */
497*10d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, dp->d_name);
498*10d63b7dSRichard Lowe (void) wcscpy(file_name_p, wcs_buffer);
499*10d63b7dSRichard Lowe file = GETNAME(file_name, FIND_LENGTH);
500*10d63b7dSRichard Lowe file->stat.is_file = true;
501*10d63b7dSRichard Lowe file->stat.has_sccs = NO_SCCS;
502*10d63b7dSRichard Lowe /*
503*10d63b7dSRichard Lowe * If this is an s. file, we also enter it as if it
504*10d63b7dSRichard Lowe * existed in the plain directory.
505*10d63b7dSRichard Lowe */
506*10d63b7dSRichard Lowe if ((dp->d_name[0] == 's') &&
507*10d63b7dSRichard Lowe (dp->d_name[1] == (int) period_char)) {
508*10d63b7dSRichard Lowe
509*10d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, dp->d_name + 2);
510*10d63b7dSRichard Lowe (void) wcscpy(plain_file_name_p, wcs_buffer);
511*10d63b7dSRichard Lowe plain_file = GETNAME(plain_file_name, FIND_LENGTH);
512*10d63b7dSRichard Lowe plain_file->stat.is_file = true;
513*10d63b7dSRichard Lowe plain_file->stat.has_sccs = HAS_SCCS;
514*10d63b7dSRichard Lowe /* if sccs dependency is already set,skip */
515*10d63b7dSRichard Lowe if(plain_file->prop) {
516*10d63b7dSRichard Lowe Property sprop = get_prop(plain_file->prop,sccs_prop);
517*10d63b7dSRichard Lowe if(sprop != NULL) {
518*10d63b7dSRichard Lowe if (sprop->body.sccs.file) {
519*10d63b7dSRichard Lowe goto try_pattern;
520*10d63b7dSRichard Lowe }
521*10d63b7dSRichard Lowe }
522*10d63b7dSRichard Lowe }
523*10d63b7dSRichard Lowe
524*10d63b7dSRichard Lowe /*
525*10d63b7dSRichard Lowe * Enter the s. file as a dependency for the
526*10d63b7dSRichard Lowe * plain file.
527*10d63b7dSRichard Lowe */
528*10d63b7dSRichard Lowe maybe_append_prop(plain_file, sccs_prop)->
529*10d63b7dSRichard Lowe body.sccs.file = file;
530*10d63b7dSRichard Lowe try_pattern:
531*10d63b7dSRichard Lowe MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2);
532*10d63b7dSRichard Lowe if ((pattern != NULL) &&
533*10d63b7dSRichard Lowe amatch(tmp_wcs_buffer, pattern)) {
534*10d63b7dSRichard Lowe if (debug_level > 0) {
535*10d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, pattern);
536*10d63b7dSRichard Lowe (void) printf(gettext("'%s: %s' due to %s expansion\n"),
537*10d63b7dSRichard Lowe line->body.line.target->
538*10d63b7dSRichard Lowe string_mb,
539*10d63b7dSRichard Lowe plain_file->string_mb,
540*10d63b7dSRichard Lowe mbs_buffer);
541*10d63b7dSRichard Lowe }
542*10d63b7dSRichard Lowe enter_dependency(line, plain_file, false);
543*10d63b7dSRichard Lowe result++;
544*10d63b7dSRichard Lowe }
545*10d63b7dSRichard Lowe }
546*10d63b7dSRichard Lowe }
547*10d63b7dSRichard Lowe (void) closedir(dir_fd);
548*10d63b7dSRichard Lowe
549*10d63b7dSRichard Lowe return result;
550*10d63b7dSRichard Lowe }
551*10d63b7dSRichard Lowe
552*10d63b7dSRichard Lowe /*
553*10d63b7dSRichard Lowe * enter_file_name(name_string, library)
554*10d63b7dSRichard Lowe *
555*10d63b7dSRichard Lowe * Helper function for read_dir().
556*10d63b7dSRichard Lowe *
557*10d63b7dSRichard Lowe * Return value:
558*10d63b7dSRichard Lowe * The Name that was entered
559*10d63b7dSRichard Lowe *
560*10d63b7dSRichard Lowe * Parameters:
561*10d63b7dSRichard Lowe * name_string Name of the file we want to enter
562*10d63b7dSRichard Lowe * library The library it is a member of, if any
563*10d63b7dSRichard Lowe *
564*10d63b7dSRichard Lowe * Global variables used:
565*10d63b7dSRichard Lowe */
566*10d63b7dSRichard Lowe static Name
enter_file_name(wchar_t * name_string,wchar_t * library)567*10d63b7dSRichard Lowe enter_file_name(wchar_t *name_string, wchar_t *library)
568*10d63b7dSRichard Lowe {
569*10d63b7dSRichard Lowe wchar_t buffer[STRING_BUFFER_LENGTH];
570*10d63b7dSRichard Lowe String_rec lib_name;
571*10d63b7dSRichard Lowe Name name;
572*10d63b7dSRichard Lowe Property prop;
573*10d63b7dSRichard Lowe
574*10d63b7dSRichard Lowe if (library == NULL) {
575*10d63b7dSRichard Lowe name = GETNAME(name_string, FIND_LENGTH);
576*10d63b7dSRichard Lowe name->stat.is_file = true;
577*10d63b7dSRichard Lowe return name;
578*10d63b7dSRichard Lowe }
579*10d63b7dSRichard Lowe
580*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(lib_name, buffer);
581*10d63b7dSRichard Lowe append_string(library, &lib_name, FIND_LENGTH);
582*10d63b7dSRichard Lowe append_char((int) parenleft_char, &lib_name);
583*10d63b7dSRichard Lowe append_string(name_string, &lib_name, FIND_LENGTH);
584*10d63b7dSRichard Lowe append_char((int) parenright_char, &lib_name);
585*10d63b7dSRichard Lowe
586*10d63b7dSRichard Lowe name = GETNAME(lib_name.buffer.start, FIND_LENGTH);
587*10d63b7dSRichard Lowe name->stat.is_file = true;
588*10d63b7dSRichard Lowe name->is_member = true;
589*10d63b7dSRichard Lowe prop = maybe_append_prop(name, member_prop);
590*10d63b7dSRichard Lowe prop->body.member.library = GETNAME(library, FIND_LENGTH);
591*10d63b7dSRichard Lowe prop->body.member.library->stat.is_file = true;
592*10d63b7dSRichard Lowe prop->body.member.entry = NULL;
593*10d63b7dSRichard Lowe prop->body.member.member = GETNAME(name_string, FIND_LENGTH);
594*10d63b7dSRichard Lowe prop->body.member.member->stat.is_file = true;
595*10d63b7dSRichard Lowe return name;
596*10d63b7dSRichard Lowe }
597*10d63b7dSRichard Lowe
598*10d63b7dSRichard Lowe /*
599*10d63b7dSRichard Lowe * star_match(string, pattern)
600*10d63b7dSRichard Lowe *
601*10d63b7dSRichard Lowe * This is a regular shell type wildcard pattern matcher
602*10d63b7dSRichard Lowe * It is used when xpanding wildcards in dependency lists
603*10d63b7dSRichard Lowe *
604*10d63b7dSRichard Lowe * Return value:
605*10d63b7dSRichard Lowe * Indication if the string matched the pattern
606*10d63b7dSRichard Lowe *
607*10d63b7dSRichard Lowe * Parameters:
608*10d63b7dSRichard Lowe * string String to match
609*10d63b7dSRichard Lowe * pattern Pattern to match it against
610*10d63b7dSRichard Lowe *
611*10d63b7dSRichard Lowe * Global variables used:
612*10d63b7dSRichard Lowe */
613*10d63b7dSRichard Lowe static Boolean
star_match(register wchar_t * string,register wchar_t * pattern)614*10d63b7dSRichard Lowe star_match(register wchar_t *string, register wchar_t *pattern)
615*10d63b7dSRichard Lowe {
616*10d63b7dSRichard Lowe register int pattern_ch;
617*10d63b7dSRichard Lowe
618*10d63b7dSRichard Lowe switch (*pattern) {
619*10d63b7dSRichard Lowe case 0:
620*10d63b7dSRichard Lowe return succeeded;
621*10d63b7dSRichard Lowe case bracketleft_char:
622*10d63b7dSRichard Lowe case question_char:
623*10d63b7dSRichard Lowe case asterisk_char:
624*10d63b7dSRichard Lowe while (*string) {
625*10d63b7dSRichard Lowe if (amatch(string++, pattern)) {
626*10d63b7dSRichard Lowe return succeeded;
627*10d63b7dSRichard Lowe }
628*10d63b7dSRichard Lowe }
629*10d63b7dSRichard Lowe break;
630*10d63b7dSRichard Lowe default:
631*10d63b7dSRichard Lowe pattern_ch = (int) *pattern++;
632*10d63b7dSRichard Lowe while (*string) {
633*10d63b7dSRichard Lowe if ((*string++ == pattern_ch) &&
634*10d63b7dSRichard Lowe amatch(string, pattern)) {
635*10d63b7dSRichard Lowe return succeeded;
636*10d63b7dSRichard Lowe }
637*10d63b7dSRichard Lowe }
638*10d63b7dSRichard Lowe break;
639*10d63b7dSRichard Lowe }
640*10d63b7dSRichard Lowe return failed;
641*10d63b7dSRichard Lowe }
642*10d63b7dSRichard Lowe
643*10d63b7dSRichard Lowe /*
644*10d63b7dSRichard Lowe * amatch(string, pattern)
645*10d63b7dSRichard Lowe *
646*10d63b7dSRichard Lowe * Helper function for shell pattern matching
647*10d63b7dSRichard Lowe *
648*10d63b7dSRichard Lowe * Return value:
649*10d63b7dSRichard Lowe * Indication if the string matched the pattern
650*10d63b7dSRichard Lowe *
651*10d63b7dSRichard Lowe * Parameters:
652*10d63b7dSRichard Lowe * string String to match
653*10d63b7dSRichard Lowe * pattern Pattern to match it against
654*10d63b7dSRichard Lowe *
655*10d63b7dSRichard Lowe * Global variables used:
656*10d63b7dSRichard Lowe */
657*10d63b7dSRichard Lowe static Boolean
amatch(register wchar_t * string,register wchar_t * pattern)658*10d63b7dSRichard Lowe amatch(register wchar_t *string, register wchar_t *pattern)
659*10d63b7dSRichard Lowe {
660*10d63b7dSRichard Lowe register long lower_bound;
661*10d63b7dSRichard Lowe register long string_ch;
662*10d63b7dSRichard Lowe register long pattern_ch;
663*10d63b7dSRichard Lowe register int k;
664*10d63b7dSRichard Lowe
665*10d63b7dSRichard Lowe top:
666*10d63b7dSRichard Lowe for (; 1; pattern++, string++) {
667*10d63b7dSRichard Lowe lower_bound = 017777777777;
668*10d63b7dSRichard Lowe string_ch = *string;
669*10d63b7dSRichard Lowe switch (pattern_ch = *pattern) {
670*10d63b7dSRichard Lowe case bracketleft_char:
671*10d63b7dSRichard Lowe k = 0;
672*10d63b7dSRichard Lowe while ((pattern_ch = *++pattern) != 0) {
673*10d63b7dSRichard Lowe switch (pattern_ch) {
674*10d63b7dSRichard Lowe case bracketright_char:
675*10d63b7dSRichard Lowe if (!k) {
676*10d63b7dSRichard Lowe return failed;
677*10d63b7dSRichard Lowe }
678*10d63b7dSRichard Lowe string++;
679*10d63b7dSRichard Lowe pattern++;
680*10d63b7dSRichard Lowe goto top;
681*10d63b7dSRichard Lowe case hyphen_char:
682*10d63b7dSRichard Lowe k |= (lower_bound <= string_ch) &&
683*10d63b7dSRichard Lowe (string_ch <=
684*10d63b7dSRichard Lowe (pattern_ch = pattern[1]));
685*10d63b7dSRichard Lowe default:
686*10d63b7dSRichard Lowe if (string_ch ==
687*10d63b7dSRichard Lowe (lower_bound = pattern_ch)) {
688*10d63b7dSRichard Lowe k++;
689*10d63b7dSRichard Lowe }
690*10d63b7dSRichard Lowe }
691*10d63b7dSRichard Lowe }
692*10d63b7dSRichard Lowe return failed;
693*10d63b7dSRichard Lowe case asterisk_char:
694*10d63b7dSRichard Lowe return star_match(string, ++pattern);
695*10d63b7dSRichard Lowe case 0:
696*10d63b7dSRichard Lowe return BOOLEAN(!string_ch);
697*10d63b7dSRichard Lowe case question_char:
698*10d63b7dSRichard Lowe if (string_ch == 0) {
699*10d63b7dSRichard Lowe return failed;
700*10d63b7dSRichard Lowe }
701*10d63b7dSRichard Lowe break;
702*10d63b7dSRichard Lowe default:
703*10d63b7dSRichard Lowe if (pattern_ch != string_ch) {
704*10d63b7dSRichard Lowe return failed;
705*10d63b7dSRichard Lowe }
706*10d63b7dSRichard Lowe break;
707*10d63b7dSRichard Lowe }
708*10d63b7dSRichard Lowe }
709*10d63b7dSRichard Lowe /* NOTREACHED */
710*10d63b7dSRichard Lowe }
711*10d63b7dSRichard Lowe
712