xref: /onnv-gate/usr/src/cmd/fs.d/cachefs/cachefspack/docmds.c (revision 633:04519cb7de3b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*633Sgt29601  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <locale.h>
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/param.h>
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate #include <string.h>
340Sstevel@tonic-gate #include <errno.h>
350Sstevel@tonic-gate #include <search.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #include <dirent.h>
380Sstevel@tonic-gate #include <fnmatch.h>
390Sstevel@tonic-gate #include <sys/stat.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #include "rules.h"
420Sstevel@tonic-gate 
430Sstevel@tonic-gate extern char *mstrdup(const char *);
440Sstevel@tonic-gate 
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate  * The do_base_dir() function is called when a BASE command is encountered
470Sstevel@tonic-gate  * in the input directives or end-of-file is reach on the input directive
480Sstevel@tonic-gate  * file. This function causes the commands associated with the previous
490Sstevel@tonic-gate  * BASE command to be executed. for example,
500Sstevel@tonic-gate  *
510Sstevel@tonic-gate  *	BASE a/b/c
520Sstevel@tonic-gate  *	LIST ...
530Sstevel@tonic-gate  *	IGNORE ...
540Sstevel@tonic-gate  *	BASE d/e/f (this command will cause do_base_dir() to be called for
550Sstevel@tonic-gate  *		   base directory a/b/c)
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  * Input arguments:
580Sstevel@tonic-gate  *	dirpath - the BASE directory being operated on
590Sstevel@tonic-gate  *	incld_lst - A list of strings to be matched obtained from the
600Sstevel@tonic-gate  *		    LIST commands associated with the BASE directory.
610Sstevel@tonic-gate  *	excld_lst - A list of strings to be matched obtained from the
620Sstevel@tonic-gate  *		    IGNORE commands associated with the BASE directory.
630Sstevel@tonic-gate  *	func	- A function to be called for each matched file. The
640Sstevel@tonic-gate  *		  functions allow files to be  packed, unpacked,
650Sstevel@tonic-gate  *		  examined and filenames printed.
660Sstevel@tonic-gate  */
670Sstevel@tonic-gate 
680Sstevel@tonic-gate void
do_base_dir(char * dirpath,struct item * incld_lst,struct item * excld_lst,int (* func)(char *,char *,DIR *,int))690Sstevel@tonic-gate do_base_dir(char *dirpath, struct item *incld_lst, struct item *excld_lst,
700Sstevel@tonic-gate     int (*func)(char *, char *, DIR *, int))
710Sstevel@tonic-gate {
720Sstevel@tonic-gate 	struct item *iitem;
730Sstevel@tonic-gate 	int err;
740Sstevel@tonic-gate 	int files_processed = 0;
750Sstevel@tonic-gate 	struct item symlk_hd, *symlk, *symlk_sv;
760Sstevel@tonic-gate 	struct stat64 statbuf;
770Sstevel@tonic-gate 	char linkbuf[MAXPATHLEN];
780Sstevel@tonic-gate 	int sz;
790Sstevel@tonic-gate 	char *s;
800Sstevel@tonic-gate 	char *mk_base_dir(char *, char *);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate #ifdef DEBUG
830Sstevel@tonic-gate 	prtitem("Global IGNOREs", &gign_hd);
840Sstevel@tonic-gate 	prtitem("LIST cmds", &list_hd);
850Sstevel@tonic-gate 	prtitem("Local IGNOREs", &lign_hd);
860Sstevel@tonic-gate #endif /* DEBUG */
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	symlk = &symlk_hd;
900Sstevel@tonic-gate 	symlk_hd.i_next = (struct item *)0;
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	iitem  = incld_lst->i_next;
930Sstevel@tonic-gate 	if (iitem == (struct item *)0)
940Sstevel@tonic-gate 		return;
950Sstevel@tonic-gate 	while (iitem != (struct item *)0) {
960Sstevel@tonic-gate #ifdef DEBUG
970Sstevel@tonic-gate 		printf("do_base_dir: iitem->i_str = %s  iitem->i_flag = %x\n",
980Sstevel@tonic-gate 		    iitem->i_str, iitem->i_flag);
990Sstevel@tonic-gate 		fflush(stdout);
1000Sstevel@tonic-gate #endif /* DEBUG */
1010Sstevel@tonic-gate 		err = do_list_item(dirpath, iitem->i_str,
1020Sstevel@tonic-gate 		    iitem->i_flag, excld_lst, 0, &symlk, func);
1030Sstevel@tonic-gate 		if (err == 0) {
1040Sstevel@tonic-gate 			fprintf(stderr,
1050Sstevel@tonic-gate 			    gettext("cachefspack: basedir = %s"),
1060Sstevel@tonic-gate 			    dirpath);
1070Sstevel@tonic-gate 			fprintf(stderr,
1080Sstevel@tonic-gate 			    gettext("    %s - no file(s) selected\n"),
1090Sstevel@tonic-gate 			    iitem->i_str);
1100Sstevel@tonic-gate 		}
1110Sstevel@tonic-gate 		iitem = iitem->i_next;
1120Sstevel@tonic-gate 	};
1130Sstevel@tonic-gate 	/*
1140Sstevel@tonic-gate 	 * Invoke 'func' for each component of the BASE
1150Sstevel@tonic-gate 	 * directory.
1160Sstevel@tonic-gate 	 */
1170Sstevel@tonic-gate 	func_dir_path(dirpath, func);
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	if (lstat64(dirpath, &statbuf) < 0) {
1200Sstevel@tonic-gate 		perror(gettext("Can't stat base directory"));
1210Sstevel@tonic-gate 	} else {
1220Sstevel@tonic-gate 		if (S_ISLNK(statbuf.st_mode)) {
1230Sstevel@tonic-gate 			sz = readlink(dirpath, linkbuf, MAXPATHLEN-1);
1240Sstevel@tonic-gate 			if (sz > 0) {
1250Sstevel@tonic-gate 				linkbuf[sz] = '\0';
1260Sstevel@tonic-gate 				s = mk_base_dir(dirpath, linkbuf);
1270Sstevel@tonic-gate 				if (s != (char *)0) {
1280Sstevel@tonic-gate 					func_dir_path(s, func);
1290Sstevel@tonic-gate 				}
1300Sstevel@tonic-gate 			}
1310Sstevel@tonic-gate 		}
1320Sstevel@tonic-gate 	}
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate #ifdef DEBUG
1350Sstevel@tonic-gate 	prtitem("Symbolic Links", &symlk_hd);
1360Sstevel@tonic-gate #endif /* DEBUG */
1370Sstevel@tonic-gate 	iitem = symlk_hd.i_next;
1380Sstevel@tonic-gate 	if (iitem == (struct item *)0)
1390Sstevel@tonic-gate 		return;
1400Sstevel@tonic-gate 	while (iitem != (struct item *)0) {
1410Sstevel@tonic-gate #ifdef DEBUG
1420Sstevel@tonic-gate 		printf("do_bas sl: iitem->i_str = %s  iitem->i_flag = %x\n",
1430Sstevel@tonic-gate 		    iitem->i_str, iitem->i_flag);
1440Sstevel@tonic-gate 		fflush(stdout);
1450Sstevel@tonic-gate #endif /* DEBUG */
1460Sstevel@tonic-gate 		files_processed = do_list_item(iitem->i_str, "*",
1470Sstevel@tonic-gate 		    (LF_SYMLINK | LF_REGEX), excld_lst, 0, &symlk, func);
1480Sstevel@tonic-gate 		if (files_processed) {
1490Sstevel@tonic-gate 			/*
1500Sstevel@tonic-gate 			 * Invoke 'func' for each component of the BASE
1510Sstevel@tonic-gate 			 * directory.
1520Sstevel@tonic-gate 			 */
1530Sstevel@tonic-gate 			func_dir_path(iitem->i_str, func);
1540Sstevel@tonic-gate 		}
1550Sstevel@tonic-gate 		symlk_sv = iitem;
1560Sstevel@tonic-gate 		iitem = iitem->i_next;
1570Sstevel@tonic-gate 		symlk_hd.i_next = iitem;
1580Sstevel@tonic-gate 		free(symlk_sv);
1590Sstevel@tonic-gate #ifdef DEBUG
1600Sstevel@tonic-gate 		prtitem("Symbolic Links loop", &symlk_hd);
1610Sstevel@tonic-gate #endif /* DEBUG */
1620Sstevel@tonic-gate 	}
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate /*
1660Sstevel@tonic-gate  * The do_list_item() function is called for each LIST item associated with
1670Sstevel@tonic-gate  * a BASE directory. It does the work of descending directories and matching
1680Sstevel@tonic-gate  * filenames.
1690Sstevel@tonic-gate  *
1700Sstevel@tonic-gate  * Input arguments:
1710Sstevel@tonic-gate  *	dirpath - the BASE directory being operated on
1720Sstevel@tonic-gate  *	pat - The argument from the LIST command to match
1730Sstevel@tonic-gate  *	flags - Flags which affect how patterns are matched:
1740Sstevel@tonic-gate  *		LF_STRIP_DOTSLASH - means strip off "." and/or "/" at the
1750Sstevel@tonic-gate  *				    beginning of the pattern to match.
1760Sstevel@tonic-gate  *		LF_REGEX - Means match the pattern as a regular expression.
1770Sstevel@tonic-gate  *			   Otherwise, an exact match of characters is required.
1780Sstevel@tonic-gate  *	excld_lst - A list of strings to be matched obtained from the
1790Sstevel@tonic-gate  *		    IGNORE commands associated with the BASE directory.
1800Sstevel@tonic-gate  *	func - A function to be called for each matched file. The
1810Sstevel@tonic-gate  *		functions allow files to be  packed, unpacked,
1820Sstevel@tonic-gate  *		examined and filenames printed.
1830Sstevel@tonic-gate  *
1840Sstevel@tonic-gate  * Return values:
1850Sstevel@tonic-gate  *	0 -  'func' NOT invoked for any file
1860Sstevel@tonic-gate  *	1 -  'func' invoked for at least 1 file
1870Sstevel@tonic-gate  */
1880Sstevel@tonic-gate int
do_list_item(char * dirpath,char * pat,int flags,struct item * excld_lst,DIR * pdir,struct item ** symlk_lst,int (* func)(char *,char *,DIR *,int))1890Sstevel@tonic-gate do_list_item(char *dirpath, char *pat, int flags, struct item *excld_lst,
1900Sstevel@tonic-gate     DIR *pdir, struct item **symlk_lst, int (*func)(char *, char *, DIR *, int))
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate 	static char statnam[MAXPATHLEN];
1930Sstevel@tonic-gate 	static int glastpos = 0;
1940Sstevel@tonic-gate 	static int basedir_lastpos;
1950Sstevel@tonic-gate 	static int depth = 0;
1960Sstevel@tonic-gate 	static int unwind = 0;
1970Sstevel@tonic-gate 	static int do_dir = 0;
1980Sstevel@tonic-gate 	static int sl_cnt;
1990Sstevel@tonic-gate 	static int retval;
2000Sstevel@tonic-gate 	static char linkbuf[MAXPATHLEN];
2010Sstevel@tonic-gate 	DIR *dir, *parent_dir;
2020Sstevel@tonic-gate 	struct dirent64 *dirent;
2030Sstevel@tonic-gate 	int match;
2040Sstevel@tonic-gate 	int err;
2050Sstevel@tonic-gate 	struct stat64 statbuf;
2060Sstevel@tonic-gate 	int llastpos;
2070Sstevel@tonic-gate 	struct item *eitem;
2080Sstevel@tonic-gate 	int excld_flag;
2090Sstevel@tonic-gate 	char *p;
2100Sstevel@tonic-gate 	int diropn;
2110Sstevel@tonic-gate 	int len;
2120Sstevel@tonic-gate 	int sz;
2130Sstevel@tonic-gate 	void process_symlk();
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	strcpy(&statnam[glastpos], dirpath);
2160Sstevel@tonic-gate 	len = strlen(statnam) - 1;
2170Sstevel@tonic-gate 	if (statnam[len] != '/') {
2180Sstevel@tonic-gate 		strcat(statnam, "/");
2190Sstevel@tonic-gate 	}
2200Sstevel@tonic-gate 	parent_dir = pdir;
2210Sstevel@tonic-gate 	llastpos = glastpos;
2220Sstevel@tonic-gate 	glastpos = strlen(statnam);
2230Sstevel@tonic-gate 	if (depth == 0) {
2240Sstevel@tonic-gate 		basedir_lastpos = glastpos;
2250Sstevel@tonic-gate 		sl_cnt = slash_cnt(pat);
2260Sstevel@tonic-gate 		retval = 0;
2270Sstevel@tonic-gate 	}
2280Sstevel@tonic-gate 	depth++;
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	diropn = 0;
2310Sstevel@tonic-gate 	dir = opendir(statnam);
2320Sstevel@tonic-gate 	if (dir == NULL) {
2330Sstevel@tonic-gate 		fprintf(stderr, gettext("\ncachefspack: %s - "), statnam);
2340Sstevel@tonic-gate 		perror(gettext("Can't open directory"));
2350Sstevel@tonic-gate 		goto out;
2360Sstevel@tonic-gate 	}
2370Sstevel@tonic-gate 	diropn = 1;
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	while (1) {
2400Sstevel@tonic-gate 		dirent = readdir64(dir);
2410Sstevel@tonic-gate 		if (dirent == NULL) { /* EOF */
2420Sstevel@tonic-gate 			if ((depth-1) > do_dir) {
2430Sstevel@tonic-gate 				do_dir = depth - 1;
2440Sstevel@tonic-gate 			}
2450Sstevel@tonic-gate 			break;
2460Sstevel@tonic-gate 		}
2470Sstevel@tonic-gate 		/*
2480Sstevel@tonic-gate 		 * If file is '..' skip it
2490Sstevel@tonic-gate 		 */
2500Sstevel@tonic-gate 		if (strcmp(dirent->d_name, "..") == 0) {
2510Sstevel@tonic-gate 			continue;
2520Sstevel@tonic-gate 		}
2530Sstevel@tonic-gate 		/*
2540Sstevel@tonic-gate 		 * Apply excludes if this is not a LISTed directory
2550Sstevel@tonic-gate 		 * NOTE: names from IGNORE commands are matched against the
2560Sstevel@tonic-gate 		 *	 component name(a name between '/' marks), not the
2570Sstevel@tonic-gate 		 *	 whole pathname.
2580Sstevel@tonic-gate 		 */
2590Sstevel@tonic-gate 		if (flags & LF_SYMLINK) {
2600Sstevel@tonic-gate 			match = ((depth-1) >= sl_cnt);
2610Sstevel@tonic-gate 		} else {
2620Sstevel@tonic-gate 			match = ((depth-1) > sl_cnt);
2630Sstevel@tonic-gate 		}
2640Sstevel@tonic-gate 		if (match) {
2650Sstevel@tonic-gate 			eitem = excld_lst->i_next;
2660Sstevel@tonic-gate 			excld_flag = 0;
2670Sstevel@tonic-gate 			while (eitem != (struct item *)0) {
2680Sstevel@tonic-gate 				match = gmatch(dirent->d_name, eitem->i_str);
2690Sstevel@tonic-gate 				if (match == 1) {
2700Sstevel@tonic-gate 					excld_flag = 1;
2710Sstevel@tonic-gate 					break;
2720Sstevel@tonic-gate 				}
2730Sstevel@tonic-gate 				eitem = eitem->i_next;
2740Sstevel@tonic-gate 			}
2750Sstevel@tonic-gate 			if (excld_flag == 1) {
2760Sstevel@tonic-gate 				continue;
2770Sstevel@tonic-gate 			}
2780Sstevel@tonic-gate 		}
2790Sstevel@tonic-gate 		strcpy(&statnam[glastpos], dirent->d_name);
2800Sstevel@tonic-gate 		err = lstat64(statnam, &statbuf);
2810Sstevel@tonic-gate 		if (err < 0) {
2820Sstevel@tonic-gate 			fprintf(stderr,
2830Sstevel@tonic-gate 			    gettext("cachefspack: %s - stat failed"),
2840Sstevel@tonic-gate 			    statnam);
2850Sstevel@tonic-gate 			perror(gettext(" "));
2860Sstevel@tonic-gate 			continue;
2870Sstevel@tonic-gate 		}
2880Sstevel@tonic-gate 		p = pat;
2890Sstevel@tonic-gate 		if (flags & LF_STRIP_DOTSLASH) {
2900Sstevel@tonic-gate 			if (strncmp(p, "./", 2) == 0) {
2910Sstevel@tonic-gate 				p += 2;
2920Sstevel@tonic-gate 			}
2930Sstevel@tonic-gate 		}
2940Sstevel@tonic-gate 		if (S_ISDIR(statbuf.st_mode)) {
2950Sstevel@tonic-gate #ifdef DEBUG
2960Sstevel@tonic-gate 			printf("directory:  &statnam[basedir_lastpos] = %s\n",
2970Sstevel@tonic-gate 			&statnam[basedir_lastpos]);
2980Sstevel@tonic-gate 			printf("statbuf.st_mode = %o\n", statbuf.st_mode);
2990Sstevel@tonic-gate 			printf("depth = %d sl_cnt = %d\n", depth, sl_cnt);
3000Sstevel@tonic-gate 			fflush(stdout);
3010Sstevel@tonic-gate #endif /* DEBUG */
3020Sstevel@tonic-gate 			if ((depth-1) == sl_cnt) {
3030Sstevel@tonic-gate 				if (flags & LF_REGEX) {
3040Sstevel@tonic-gate 					match =
3050Sstevel@tonic-gate 					    gmatch(&statnam[basedir_lastpos],
3060Sstevel@tonic-gate 					    p);
3070Sstevel@tonic-gate 				} else {
3080Sstevel@tonic-gate 					match =
3090Sstevel@tonic-gate 					    (strcmp(&statnam[basedir_lastpos],
3100Sstevel@tonic-gate 					    p) == 0);
3110Sstevel@tonic-gate 				}
3120Sstevel@tonic-gate 				if (match) {
3130Sstevel@tonic-gate 					/*
3140Sstevel@tonic-gate 					 * Don't descend '.' directory
3150Sstevel@tonic-gate 					 * but match it
3160Sstevel@tonic-gate 					 */
3170Sstevel@tonic-gate 					if (strcmp(dirent->d_name, ".") != 0) {
3180Sstevel@tonic-gate 						do_list_item(dirent->d_name,
3190Sstevel@tonic-gate 						    "*", flags, excld_lst,
3200Sstevel@tonic-gate 						    dir, symlk_lst, func);
3210Sstevel@tonic-gate 					} else {
3220Sstevel@tonic-gate 						if ((depth-1) > do_dir) {
3230Sstevel@tonic-gate 							do_dir = depth - 1;
3240Sstevel@tonic-gate 						}
3250Sstevel@tonic-gate 						(void) func(statnam,
3260Sstevel@tonic-gate 						    dirent->d_name,
3270Sstevel@tonic-gate 						    dir, depth);
3280Sstevel@tonic-gate 					}
3290Sstevel@tonic-gate 					retval = 1;
3300Sstevel@tonic-gate 					if (unwind = discont_srch(flags, p)) {
3310Sstevel@tonic-gate 						goto out;
3320Sstevel@tonic-gate 					}
3330Sstevel@tonic-gate 				}
3340Sstevel@tonic-gate 				continue;
3350Sstevel@tonic-gate 			}
3360Sstevel@tonic-gate 			/*
3370Sstevel@tonic-gate 			 * Don't descend '.' directory
3380Sstevel@tonic-gate 			 */
3390Sstevel@tonic-gate 			if (strcmp(dirent->d_name, ".") != 0) {
3400Sstevel@tonic-gate 				do_list_item(dirent->d_name, p, flags,
3410Sstevel@tonic-gate 				    excld_lst, dir, symlk_lst, func);
3420Sstevel@tonic-gate 			}
3430Sstevel@tonic-gate 			if (unwind) {
3440Sstevel@tonic-gate 				goto out;
3450Sstevel@tonic-gate 			}
3460Sstevel@tonic-gate 			continue;
3470Sstevel@tonic-gate 		}
3480Sstevel@tonic-gate 		if (S_ISLNK(statbuf.st_mode)) {
3490Sstevel@tonic-gate 			if (flags & LF_SYMLINK)
3500Sstevel@tonic-gate 			    continue;
3510Sstevel@tonic-gate #ifdef DEBUG
3520Sstevel@tonic-gate 			printf("sym link : &statnam[basedir_lastpos] = %s\n",
3530Sstevel@tonic-gate 			&statnam[basedir_lastpos]);
3540Sstevel@tonic-gate 			printf("statbuf.st_mode = %o\n", statbuf.st_mode);
3550Sstevel@tonic-gate 			printf("statnam = %s\n", statnam);
3560Sstevel@tonic-gate #endif /* DEBUG */
3570Sstevel@tonic-gate 			/*
3580Sstevel@tonic-gate 			 * Symbolic link was explicitly specified or matches a
3590Sstevel@tonic-gate 			 * regular expression in a LIST item. Thus we follow
3600Sstevel@tonic-gate 			 * the link. Otherwise, just call 'func' for the link
3610Sstevel@tonic-gate 			 * name.
3620Sstevel@tonic-gate 			 */
3630Sstevel@tonic-gate #ifdef DEBUG
3640Sstevel@tonic-gate 			printf("depth = %d  sl_cnt = %d\n", depth, sl_cnt);
3650Sstevel@tonic-gate 			fflush(stdout);
3660Sstevel@tonic-gate #endif /* DEBUG */
3670Sstevel@tonic-gate 			if ((depth-1) == sl_cnt) {
3680Sstevel@tonic-gate 				if (flags & LF_REGEX) {
3690Sstevel@tonic-gate 					match =
3700Sstevel@tonic-gate 					    gmatch(&statnam[basedir_lastpos],
3710Sstevel@tonic-gate 					    p);
3720Sstevel@tonic-gate 				} else {
3730Sstevel@tonic-gate 					match =
3740Sstevel@tonic-gate 					    (strcmp(&statnam[basedir_lastpos],
3750Sstevel@tonic-gate 					    p) == 0);
3760Sstevel@tonic-gate 				}
3770Sstevel@tonic-gate #ifdef DEBUG
3780Sstevel@tonic-gate 				printf("match = %d\n", match);
3790Sstevel@tonic-gate 				fflush(stdout);
3800Sstevel@tonic-gate #endif /* DEBUG */
3810Sstevel@tonic-gate 				if (match) {
3820Sstevel@tonic-gate 					if ((depth-1) > do_dir) {
3830Sstevel@tonic-gate 						do_dir = depth - 1;
3840Sstevel@tonic-gate 					}
3850Sstevel@tonic-gate 					retval = 1;
3860Sstevel@tonic-gate 					(void) func(statnam, dirent->d_name,
3870Sstevel@tonic-gate 					    dir, depth);
3880Sstevel@tonic-gate 					sz = readlink(
3890Sstevel@tonic-gate 					    statnam, linkbuf, MAXPATHLEN-1);
3900Sstevel@tonic-gate #ifdef DEBUG
3910Sstevel@tonic-gate 					printf("linkbuf = %s\n", linkbuf);
3920Sstevel@tonic-gate 					printf("sz = %d\n", sz);
3930Sstevel@tonic-gate 					fflush(stdout);
3940Sstevel@tonic-gate #endif /* DEBUG */
3950Sstevel@tonic-gate 					if (sz < 0) {
3960Sstevel@tonic-gate 						continue;
3970Sstevel@tonic-gate 					}
3980Sstevel@tonic-gate 					linkbuf[sz] = '\0';
3990Sstevel@tonic-gate 					process_symlk(linkbuf, statnam,
4000Sstevel@tonic-gate 					    glastpos, symlk_lst, func);
4010Sstevel@tonic-gate 					if (unwind = discont_srch(flags, p)) {
4020Sstevel@tonic-gate 						goto out;
4030Sstevel@tonic-gate 					}
4040Sstevel@tonic-gate 				}
4050Sstevel@tonic-gate 			}
4060Sstevel@tonic-gate 			if ((depth-1) > sl_cnt) {
4070Sstevel@tonic-gate 				if ((depth-1) > do_dir) {
4080Sstevel@tonic-gate 					do_dir = depth - 1;
4090Sstevel@tonic-gate 				}
4100Sstevel@tonic-gate 				retval = 1;
4110Sstevel@tonic-gate 				(void) func(statnam, dirent->d_name, dir,
4120Sstevel@tonic-gate 				    depth);
4130Sstevel@tonic-gate 				sz = readlink(statnam, linkbuf, MAXPATHLEN-1);
4140Sstevel@tonic-gate #ifdef DEBUG
4150Sstevel@tonic-gate 				printf("linkbuf = %s\n", linkbuf);
4160Sstevel@tonic-gate 				printf("sz = %d\n", sz);
4170Sstevel@tonic-gate 				fflush(stdout);
4180Sstevel@tonic-gate #endif /* DEBUG */
4190Sstevel@tonic-gate 				if (sz < 0) {
4200Sstevel@tonic-gate 					continue;
4210Sstevel@tonic-gate 				}
4220Sstevel@tonic-gate 				linkbuf[sz] = '\0';
4230Sstevel@tonic-gate 				process_symlk(linkbuf, statnam, glastpos,
4240Sstevel@tonic-gate 				    symlk_lst, func);
4250Sstevel@tonic-gate 				if (unwind = discont_srch(flags, p)) {
4260Sstevel@tonic-gate 					goto out;
4270Sstevel@tonic-gate 				}
4280Sstevel@tonic-gate 			}
4290Sstevel@tonic-gate 			continue;
4300Sstevel@tonic-gate 		}
4310Sstevel@tonic-gate 		/*
4320Sstevel@tonic-gate 		 * File must be a regular file -
4330Sstevel@tonic-gate 		 * Does it match the specified pattern?
4340Sstevel@tonic-gate 		 */
4350Sstevel@tonic-gate #ifdef DEBUG
4360Sstevel@tonic-gate 		printf("reg file : &statnam[basedir_lastpos] = %s  p = %s\n",
4370Sstevel@tonic-gate 			&statnam[basedir_lastpos], p);
4380Sstevel@tonic-gate 		printf("statbuf.st_mode = %o\n", statbuf.st_mode);
4390Sstevel@tonic-gate 		fflush(stdout);
4400Sstevel@tonic-gate #endif /* DEBUG */
4410Sstevel@tonic-gate 		if (flags & LF_REGEX) {
4420Sstevel@tonic-gate 			match = gmatch(&statnam[basedir_lastpos], p);
4430Sstevel@tonic-gate 		} else {
4440Sstevel@tonic-gate 			match = (strcmp(&statnam[basedir_lastpos], p) == 0);
4450Sstevel@tonic-gate 		}
4460Sstevel@tonic-gate 		if (!match) {
4470Sstevel@tonic-gate 			continue;
4480Sstevel@tonic-gate 		}
4490Sstevel@tonic-gate 		if ((depth - 1) > do_dir) {
4500Sstevel@tonic-gate 			do_dir = depth - 1;
4510Sstevel@tonic-gate 		}
4520Sstevel@tonic-gate 		retval = 1;
4530Sstevel@tonic-gate 		(void) func(statnam, dirent->d_name, dir, depth);
4540Sstevel@tonic-gate 		/*
4550Sstevel@tonic-gate 		 * If the file is an executable, check to see if shared
4560Sstevel@tonic-gate 		 * libraries need to be packed.
4570Sstevel@tonic-gate 		 */
4580Sstevel@tonic-gate 		if (statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
4590Sstevel@tonic-gate 			process_executable(statnam, func);
4600Sstevel@tonic-gate 		}
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 		if (unwind = discont_srch(flags, p)) {
4630Sstevel@tonic-gate 			goto out;
4640Sstevel@tonic-gate 		}
4650Sstevel@tonic-gate 	}
4660Sstevel@tonic-gate out:
4670Sstevel@tonic-gate 	depth--;
4680Sstevel@tonic-gate 	if (depth == 0) {
4690Sstevel@tonic-gate 		unwind = 0;
4700Sstevel@tonic-gate 	}
4710Sstevel@tonic-gate 	statnam[glastpos] = '\0';
4720Sstevel@tonic-gate 	if (do_dir) {
4730Sstevel@tonic-gate 		do_dir--;
4740Sstevel@tonic-gate #ifdef DEBUG
4750Sstevel@tonic-gate 		printf("out:  call func\n");
4760Sstevel@tonic-gate 		fflush(stdout);
4770Sstevel@tonic-gate 		printf("out: statnam = %s\n", statnam);
4780Sstevel@tonic-gate 		fflush(stdout);
4790Sstevel@tonic-gate 		printf("out: &statnam[llastpos] = %s\n", &statnam[llastpos]);
4800Sstevel@tonic-gate 		fflush(stdout);
4810Sstevel@tonic-gate #endif /* DEBUG */
4820Sstevel@tonic-gate 		if (func(statnam, &statnam[llastpos], parent_dir, depth) < 0) {
4830Sstevel@tonic-gate 			do_dir = 0;
4840Sstevel@tonic-gate 		}
4850Sstevel@tonic-gate 	}
4860Sstevel@tonic-gate 	glastpos = llastpos;
4870Sstevel@tonic-gate 	if (diropn)
4880Sstevel@tonic-gate 	    closedir(dir);
4890Sstevel@tonic-gate 	return (retval);
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate /*
4930Sstevel@tonic-gate  * Count all the '/' characters in the string except for those
4940Sstevel@tonic-gate  * in the first character position and last character position
4950Sstevel@tonic-gate  * of the string.
4960Sstevel@tonic-gate  */
4970Sstevel@tonic-gate int
slash_cnt(char * str)498*633Sgt29601 slash_cnt(char *str)
4990Sstevel@tonic-gate {
5000Sstevel@tonic-gate 	char *p = str;
5010Sstevel@tonic-gate 	int len;
5020Sstevel@tonic-gate 	int i;
5030Sstevel@tonic-gate 	int count = 0;
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate #ifdef DEBUG
5060Sstevel@tonic-gate 	printf("slash_cnt: str = %s", str);
5070Sstevel@tonic-gate #endif /* DEBUG */
5080Sstevel@tonic-gate 	/*
5090Sstevel@tonic-gate 	 * NOTE //a, /a and ./a are the same
5100Sstevel@tonic-gate 	 */
5110Sstevel@tonic-gate 	if (*p == '.')
5120Sstevel@tonic-gate 	    p++;
5130Sstevel@tonic-gate 	while (*p == '/')
5140Sstevel@tonic-gate 	    p++;
5150Sstevel@tonic-gate 	len = strlen(str) - 1;
5160Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
5170Sstevel@tonic-gate 		if (*p == '/') {
5180Sstevel@tonic-gate 			count++;
5190Sstevel@tonic-gate 			i--;
5200Sstevel@tonic-gate 			while (*p == '/') {
5210Sstevel@tonic-gate 				p++;
5220Sstevel@tonic-gate 				i++;
5230Sstevel@tonic-gate 			}
5240Sstevel@tonic-gate 		} else {
5250Sstevel@tonic-gate 			p++;
5260Sstevel@tonic-gate 		}
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate #ifdef DEBUG
5290Sstevel@tonic-gate 	printf("  count = %d\n", count);
5300Sstevel@tonic-gate 	fflush(stdout);
5310Sstevel@tonic-gate #endif /* DEBUG */
5320Sstevel@tonic-gate 	return (count);
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate /*
5360Sstevel@tonic-gate  * For each directory in the path name, call 'func'.
5370Sstevel@tonic-gate  */
5380Sstevel@tonic-gate int
func_dir_path(char * path,int (* func)(char *,char *,DIR *,int))5390Sstevel@tonic-gate func_dir_path(char *path, int (*func)(char *, char *, DIR *, int))
5400Sstevel@tonic-gate {
5410Sstevel@tonic-gate 	char *dnam;
5420Sstevel@tonic-gate 	char *fnam;
5430Sstevel@tonic-gate 	char *pathtmp;
5440Sstevel@tonic-gate 	DIR *dir;
5450Sstevel@tonic-gate 	char *get_fname(char *);
5460Sstevel@tonic-gate 	char *get_dirname(char *);
5470Sstevel@tonic-gate 	ENTRY hitem, *hitemp;
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate #ifdef DEBUG
5500Sstevel@tonic-gate 	printf("func_dir_path: path = %s\n", path);
5510Sstevel@tonic-gate 	fflush(stdout);
5520Sstevel@tonic-gate #endif /* DEBUG */
5530Sstevel@tonic-gate 	fnam = path;
5540Sstevel@tonic-gate 	dnam = path;
5550Sstevel@tonic-gate 	pathtmp = mstrdup(path);
5560Sstevel@tonic-gate 	while (fnam != NULL) {
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 		fnam = get_fname(dnam);
5590Sstevel@tonic-gate 		dnam = get_dirname(dnam);
5600Sstevel@tonic-gate 		if (fnam != (char *)0) {
5610Sstevel@tonic-gate 			if (strcmp(fnam, "..") == 0) {
5620Sstevel@tonic-gate 				free(pathtmp);
5630Sstevel@tonic-gate 				pathtmp = mstrdup(dnam);
5640Sstevel@tonic-gate 				continue;
5650Sstevel@tonic-gate 			}
5660Sstevel@tonic-gate 		}
5670Sstevel@tonic-gate #ifdef DEBUG
5680Sstevel@tonic-gate 		if (fnam != (char *)0) {
5690Sstevel@tonic-gate 			printf("func_dir_path: fnam = %s\n", fnam);
5700Sstevel@tonic-gate 		}
5710Sstevel@tonic-gate 		printf("func_dir_path: dnam = %s  pathtmp = %s\n",
5720Sstevel@tonic-gate 		    dnam,  pathtmp);
5730Sstevel@tonic-gate 		fflush(stdout);
5740Sstevel@tonic-gate #endif /* DEBUG */
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate 		hitem.key = mstrdup(pathtmp);
5770Sstevel@tonic-gate 		hitem.data = 0;
5780Sstevel@tonic-gate 		hitemp = hsearch(hitem, FIND);
5790Sstevel@tonic-gate 		if (hitemp != NULL) {
5800Sstevel@tonic-gate 			/*
5810Sstevel@tonic-gate 			 * If hash item data is 0, item has not been packed.
5820Sstevel@tonic-gate 			 * If hash item data is 1, item has been packed.
5830Sstevel@tonic-gate 			 */
5840Sstevel@tonic-gate #ifdef DEBUG
5850Sstevel@tonic-gate 			printf("func_dir_path: key = %s hitemp->data = %x\n",
5860Sstevel@tonic-gate 			    hitemp->key, hitemp->data);
5870Sstevel@tonic-gate 			fflush(stdout);
5880Sstevel@tonic-gate #endif /* DEBUG */
5890Sstevel@tonic-gate 			if (hitemp->data == (char *)1)
5900Sstevel@tonic-gate 			    break;
5910Sstevel@tonic-gate 			hitemp->data = (char *)1;
5920Sstevel@tonic-gate 		} else {
5930Sstevel@tonic-gate 			hitem.key = mstrdup(pathtmp);
5940Sstevel@tonic-gate 			hitem.data = (char *)1;
5950Sstevel@tonic-gate 			if (hsearch(hitem, ENTER) == NULL) {
5960Sstevel@tonic-gate 				fprintf(stderr,
5970Sstevel@tonic-gate 				    gettext("cachefspack: hash table full\n"));
5980Sstevel@tonic-gate 			}
5990Sstevel@tonic-gate 		}
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 		dir = opendir(dnam);
6020Sstevel@tonic-gate 		if (dir != NULL) {
6030Sstevel@tonic-gate 			if (func(pathtmp, fnam, dir, 0) < 0) {
6040Sstevel@tonic-gate #ifdef DEBUG
6050Sstevel@tonic-gate 				printf("func_dir_path: errno = %d\n", errno);
6060Sstevel@tonic-gate 				fflush(stdout);
6070Sstevel@tonic-gate #endif /* DEBUG */
6080Sstevel@tonic-gate 				closedir(dir);
6090Sstevel@tonic-gate 				return (-1);
6100Sstevel@tonic-gate 			}
6110Sstevel@tonic-gate 			closedir(dir);
6120Sstevel@tonic-gate 		} else {
6130Sstevel@tonic-gate 			printf(gettext("cachefspack:  error opening dir -"));
6140Sstevel@tonic-gate 			printf("%s\n", dnam);
6150Sstevel@tonic-gate 			fflush(stdout);
6160Sstevel@tonic-gate 		}
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 		free(pathtmp);
6190Sstevel@tonic-gate 		pathtmp = mstrdup(dnam);
6200Sstevel@tonic-gate 	}
6210Sstevel@tonic-gate 	free(pathtmp);
6220Sstevel@tonic-gate 	return (0);
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate void
process_symlk(char * lkpath,char * relpath,int rel_lastpos,struct item ** symlk,int (* func)(char *,char *,DIR *,int))6250Sstevel@tonic-gate process_symlk(char *lkpath, char *relpath, int rel_lastpos,
6260Sstevel@tonic-gate     struct item **symlk, int (*func)(char *, char *, DIR *, int))
6270Sstevel@tonic-gate {
6280Sstevel@tonic-gate 	struct stat64 lstatbuf;
6290Sstevel@tonic-gate 	char *l;
6300Sstevel@tonic-gate 	struct item *add_item(struct item *, char *, int);
6310Sstevel@tonic-gate 	int len;
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	/*
6340Sstevel@tonic-gate 	 * if the link has a relative pathname, append the name to
6350Sstevel@tonic-gate 	 * current path.
6360Sstevel@tonic-gate 	 */
6370Sstevel@tonic-gate 	if (*lkpath != '/') {
6380Sstevel@tonic-gate 		len = strlen(lkpath);
6390Sstevel@tonic-gate 		if ((len + rel_lastpos + 2) > MAXPATHLEN) {
6400Sstevel@tonic-gate 			fprintf(stderr, gettext("can't process sym link - %s"),
6410Sstevel@tonic-gate 			    lkpath);
6420Sstevel@tonic-gate 			return;
6430Sstevel@tonic-gate 		}
6440Sstevel@tonic-gate 		strcpy(&relpath[rel_lastpos], lkpath);
6450Sstevel@tonic-gate 		l = relpath;
6460Sstevel@tonic-gate 	} else {
6470Sstevel@tonic-gate 		l = lkpath;
6480Sstevel@tonic-gate 	}
6490Sstevel@tonic-gate #ifdef DEBUG
6500Sstevel@tonic-gate 	printf("process_symlk: lkpath = %s\n", lkpath);
6510Sstevel@tonic-gate 	printf("process_symlk: l = %s\n", l);
6520Sstevel@tonic-gate 	printf("lstatbuf.st_mode = %o\n", lstatbuf.st_mode);
6530Sstevel@tonic-gate 	fflush(stdout);
6540Sstevel@tonic-gate #endif /* DEBUG */
6550Sstevel@tonic-gate 	if (lstat64(l, &lstatbuf) < 0) {
6560Sstevel@tonic-gate 		fprintf(stderr, gettext("Can't lstat sym link - %s"), l);
6570Sstevel@tonic-gate 		perror(" ");
6580Sstevel@tonic-gate 		return;
6590Sstevel@tonic-gate 	}
6600Sstevel@tonic-gate 	if (S_ISDIR(lstatbuf.st_mode)) {
6610Sstevel@tonic-gate 		*symlk = add_item(*symlk, l, 0);
6620Sstevel@tonic-gate 	}
6630Sstevel@tonic-gate 	if (S_ISREG(lstatbuf.st_mode)) {
6640Sstevel@tonic-gate 		func_dir_path(l, func);
6650Sstevel@tonic-gate 	}
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate 
668*633Sgt29601 int
discont_srch(int flags,char * pat)6690Sstevel@tonic-gate discont_srch(int flags, char *pat)
6700Sstevel@tonic-gate {
6710Sstevel@tonic-gate 	char *wild;
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate #ifdef DEBUG
6740Sstevel@tonic-gate 	printf("discont_srch: flags = %x  pat = %s\n", flags, pat);
6750Sstevel@tonic-gate 	fflush(stdout);
6760Sstevel@tonic-gate #endif /* DEBUG */
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate 	/*
6790Sstevel@tonic-gate 	 * if patterns are NOT being matched as regular expressions
6800Sstevel@tonic-gate 	 * we can have at most 1 match. We got it so quit.
6810Sstevel@tonic-gate 	 */
6820Sstevel@tonic-gate 	if ((flags & LF_REGEX) != LF_REGEX) {
6830Sstevel@tonic-gate #ifdef DEBUG
6840Sstevel@tonic-gate 		printf("discont_srch: ! LF_REGEX\n");
6850Sstevel@tonic-gate 		fflush(stdout);
6860Sstevel@tonic-gate #endif /* DEBUG */
6870Sstevel@tonic-gate 		return (1);
6880Sstevel@tonic-gate 	}
6890Sstevel@tonic-gate 	/*
6900Sstevel@tonic-gate 	 * if the pattern does not contain wildcard characters and
6910Sstevel@tonic-gate 	 * we have found a match we are done.
6920Sstevel@tonic-gate 	 */
6930Sstevel@tonic-gate 	if (WILDCARD(wild, pat) == NULL) {
6940Sstevel@tonic-gate #ifdef DEBUG
6950Sstevel@tonic-gate 		printf("discont_srch: wild = %x\n", wild);
6960Sstevel@tonic-gate 		fflush(stdout);
6970Sstevel@tonic-gate #endif /* DEBUG */
6980Sstevel@tonic-gate 		return (1);
6990Sstevel@tonic-gate 	}
7000Sstevel@tonic-gate 	return (0);
7010Sstevel@tonic-gate }
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate #ifdef DEBUG
prtitem(char * str,struct item * hd)704*633Sgt29601 prtitem(char *str, struct item *hd)
7050Sstevel@tonic-gate {
7060Sstevel@tonic-gate 	struct item *p = hd->i_next;
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 	printf("\n%s\n\n", str);
7090Sstevel@tonic-gate 	while (p != (struct item *)0) {
7100Sstevel@tonic-gate 		printf("str = %s\n", p->i_str);
7110Sstevel@tonic-gate 		p = p->i_next;
7120Sstevel@tonic-gate 	}
7130Sstevel@tonic-gate }
7140Sstevel@tonic-gate #endif /* DEBUG */
715