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& 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 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& 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 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 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 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 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