⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pat_rep.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* NOTREACHED */}#ifdef __STDC__static char *range_match(register char *pattern, register int test)#elsestatic char *range_match(pattern, test)	register char *pattern;	register int test;#endif{	register char c;	register char c2;	int negate;	int ok = 0;	if (negate = (*pattern == '!'))		++pattern;	while ((c = *pattern++) != ']') {		/*		 * Illegal pattern		 */		if (c == '\0')			return (NULL);		if ((*pattern == '-') && ((c2 = pattern[1]) != '\0') &&		    (c2 != ']')) {			if ((c <= test) && (test <= c2))				ok = 1;			pattern += 2;		} else if (c == test)			ok = 1;	}	return (ok == negate ? NULL : pattern);}/* * mod_name() *	modify a selected file name. first attempt to apply replacement string *	expressions, then apply interactive file rename. We apply replacement *	string expressions to both filenames and file links (if we didn't the *	links would point to the wrong place, and we could never be able to *	move an archive that has a file link in it). When we rename files *	interactively, we store that mapping (old name to user input name) so *	if we spot any file links to the old file name in the future, we will *	know exactly how to fix the file link. * Return: *	0 continue to  process file, 1 skip this file, -1 pax is finished  */#if __STDC__intmod_name(register ARCHD *arcn)#elseintmod_name(arcn)	register ARCHD *arcn;#endif{	register int res = 0;	/*	 * IMPORTANT: We have a problem. what do we do with symlinks?	 * Modifying a hard link name makes sense, as we know the file it	 * points at should have been seen already in the archive (and if it	 * wasn't seen because of a read error or a bad archive, we lose	 * anyway). But there are no such requirements for symlinks. On one	 * hand the symlink that refers to a file in the archive will have to	 * be modified to so it will still work at its new location in the	 * file system. On the other hand a symlink that points elsewhere (and	 * should continue to do so) should not be modified. There is clearly	 * no perfect solution here. So we handle them like hardlinks. Clearly	 * a replacement made by the interactive rename mapping is very likely	 * to be correct since it applies to a single file and is an exact	 * match. The regular expression replacements are a little harder to	 * justify though. We claim that the symlink name is only likely	 * to be replaced when it points within the file tree being moved and	 * in that case it should be modified. what we really need to do is to	 * call an oracle here. :)	 */	if (rephead != NULL) {		/*		 * we have replacement strings, modify the name and the link		 * name if any.		 */		if ((res = rep_name(arcn->name, &(arcn->nlen), 1)) != 0)			return(res);		if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||		    (arcn->type == PAX_HRG)) &&		    ((res = rep_name(arcn->ln_name, &(arcn->ln_nlen), 0)) != 0))			return(res);	}	if (iflag) {		/*		 * perform interactive file rename, then map the link if any		 */		if ((res = tty_rename(arcn)) != 0)			return(res);		if ((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||		    (arcn->type == PAX_HRG))			sub_name(arcn->ln_name, &(arcn->ln_nlen));	}	return(res);}/* * tty_rename() *	Prompt the user for a replacement file name. A "." keeps the old name, *	a empty line skips the file, and an EOF on reading the tty, will cause *	pax to stop processing and exit. Otherwise the file name input, replaces *	the old one. * Return: *	0 process this file, 1 skip this file, -1 we need to exit pax */#if __STDC__static inttty_rename(register ARCHD *arcn)#elsestatic inttty_rename(arcn)	register ARCHD *arcn;#endif{	char tmpname[PAXPATHLEN+2];	int res;	/*	 * prompt user for the replacement name for a file, keep trying until	 * we get some reasonable input. Archives may have more than one file	 * on them with the same name (from updates etc). We print verbose info	 * on the file so the user knows what is up.	 */	tty_prnt("\nATTENTION: %s interactive file rename operation.\n", argv0);	for (;;) {		ls_tty(arcn);		tty_prnt("Input new name, or a \".\" to keep the old name, ");		tty_prnt("or a \"return\" to skip this file.\n");		tty_prnt("Input > ");		if (tty_read(tmpname, sizeof(tmpname)) < 0)			return(-1);		if (strcmp(tmpname, "..") == 0) {			tty_prnt("Try again, illegal file name: ..\n");			continue;		}		if (strlen(tmpname) > PAXPATHLEN) {			tty_prnt("Try again, file name too long\n");			continue;		}		break;	}	/*	 * empty file name, skips this file. a "." leaves it alone	 */	if (tmpname[0] == '\0') {		tty_prnt("Skipping file.\n");		return(1);	}	if ((tmpname[0] == '.') && (tmpname[1] == '\0')) {		tty_prnt("Processing continues, name unchanged.\n");		return(0);	}	/*	 * ok the name changed. We may run into links that point at this	 * file later. we have to remember where the user sent the file	 * in order to repair any links.	 */	tty_prnt("Processing continues, name changed to: %s\n", tmpname);	res = add_name(arcn->name, arcn->nlen, tmpname);	arcn->nlen = l_strncpy(arcn->name, tmpname, PAXPATHLEN+1);	if (res < 0)		return(-1);	return(0);}/* * set_dest() *	fix up the file name and the link name (if any) so this file will land *	in the destination directory (used during copy() -rw). * Return: *	0 if ok, -1 if failure (name too long) */#if __STDC__intset_dest(register ARCHD *arcn, char *dest_dir, int dir_len)#elseintset_dest(arcn, dest_dir, dir_len)	register ARCHD *arcn;	char *dest_dir;	int dir_len;#endif{	if (fix_path(arcn->name, &(arcn->nlen), dest_dir, dir_len) < 0)		return(-1);	/*	 * It is really hard to deal with symlinks here, we cannot be sure	 * if the name they point was moved (or will be moved). It is best to	 * leave them alone.	 */	if ((arcn->type != PAX_HLK) && (arcn->type != PAX_HRG))		return(0);	if (fix_path(arcn->ln_name, &(arcn->ln_nlen), dest_dir, dir_len) < 0)		return(-1);	return(0);}/* * fix_path *	concatenate dir_name and or_name and store the result in or_name (if *	it fits). This is one ugly function. * Return: *	0 if ok, -1 if the final name is too long */#if __STDC__static intfix_path( char *or_name, int *or_len, char *dir_name, int dir_len)#elsestatic intfix_path(or_name, or_len, dir_name, dir_len)	char *or_name;	int *or_len;	char *dir_name;	int dir_len;#endif{	register char *src;	register char *dest;	register char *start;	int len;	/*	 * we shift the or_name to the right enough to tack in the dir_name	 * at the front. We make sure we have enough space for it all before	 * we start. since dest always ends in a slash, we skip of or_name	 * if it also starts with one.	 */	start = or_name;	src = start + *or_len;	dest = src + dir_len;	if (*start == '/') {		++start;		--dest;	}	if ((len = dest - or_name) > PAXPATHLEN) {		warn(1, "File name %s/%s, too long", dir_name, start);		return(-1);	}	*or_len = len;	/*	 * enough space, shift 	 */	while (src >= start)		*dest-- = *src--;	src = dir_name + dir_len - 1;	/*	 * splice in the destination directory name	 */	while (src >= dir_name)		*dest-- = *src--;	*(or_name + len) = '\0';	return(0);}/* * rep_name() *	walk down the list of replacement strings applying each one in order. *	when we find one with a successful substitution, we modify the name *	as specified. if required, we print the results. if the resulting name *	is empty, we will skip this archive member. We use the regexp(3) *	routines (regexp() ought to win a prize as having the most cryptic *	library function manual page). *	--Parameters-- *	name is the file name we are going to apply the regular expressions to *	(and may be modified) *	nlen is the length of this name (and is modified to hold the length of *	the final string). *	prnt is a flag that says whether to print the final result. * Return: *	0 if substitution was successful, 1 if we are to skip the file (the name *	ended up empty) */#if __STDC__static intrep_name(char *name, int *nlen, int prnt)#elsestatic intrep_name(name, nlen, prnt)	char *name;	int *nlen;	int prnt;#endif{	register REPLACE *pt;	register char *inpt;	register char *outpt;	register char *endpt;	register char *rpt;	register int found = 0;	register int res;#	ifndef NET2_REGEX	regmatch_t pm[MAXSUBEXP];#	endif	char nname[PAXPATHLEN+1];	/* final result of all replacements */	char buf1[PAXPATHLEN+1];	/* where we work on the name */	/*	 * copy the name into buf1, where we will work on it. We need to keep	 * the orig string around so we can print out the result of the final	 * replacement. We build up the final result in nname. inpt points at	 * the string we apply the regular expression to. prnt is used to	 * suppress printing when we handle replacements on the link field	 * (the user already saw that substitution go by)	 */	pt = rephead;	(void)strcpy(buf1, name);	inpt = buf1;	outpt = nname;	endpt = outpt + PAXPATHLEN;	/*	 * try each replacement string in order	 */	while (pt != NULL) {		do {			/*			 * check for a successful substitution, if not go to			 * the next pattern, or cleanup if we were global			 */#			ifdef NET2_REGEX			if (regexec(pt->rcmp, inpt) == 0)#			else			if (regexec(&(pt->rcmp), inpt, MAXSUBEXP, pm, 0) != 0)#			endif				break;			/*			 * ok we found one. We have three parts, the prefix			 * which did not match, the section that did and the			 * tail (that also did not match). Copy the prefix to			 * the final output buffer (watching to make sure we			 * do not create a string too long).			 */			found = 1;#			ifdef NET2_REGEX			rpt = pt->rcmp->startp[0];#			else			rpt = inpt + pm[0].rm_so;#			endif			while ((inpt < rpt) && (outpt < endpt))				*outpt++ = *inpt++;			if (outpt == endpt)				break;			/*			 * for the second part (which matched the regular			 * expression) apply the substitution using the			 * replacement string and place it the prefix in the			 * final output. If we have problems, skip it.			 */#			ifdef NET2_REGEX			if ((res = resub(pt->rcmp,pt->nstr,outpt,endpt)) < 0) {#			else			if ((res = resub(&(pt->rcmp),pm,pt->nstr,outpt,endpt))			    < 0) {#			endif				if (prnt)					warn(1, "Replacement name error %s",					    name);				return(1);			}			outpt += res;			/*			 * we set up to look again starting at the first			 * character in the tail (of the input string right			 * after the last character matched by the regular			 * expression (inpt always points at the first char in			 * the string to process). If we are not doing a global			 * substitution, we will use inpt to copy the tail to			 * the final result. Make sure we do not overrun the			 * output buffer			 */#			ifdef NET2_REGEX			inpt = pt->rcmp->endp[0];#			else			inpt += pm[0].rm_eo;#			endif			if ((outpt == endpt) || (*inpt == '\0'))				break;			/*			 * if the user wants global we keep trying to			 * substitute until it fails, then we are done.			 */		} while (pt->flgs & GLOB);		if (found) 			break;		/*		 * a successful substitution did NOT occur, try the next one		 */		pt = pt->fow;	}	if (found) {		/*		 * we had a substitution, copy the last tail piece (if there is		 * room) to the final result		 */		while ((outpt < endpt) && (*inpt != '\0'))			*outpt++ = *inpt++;		*outpt = '\0';		if ((outpt == endpt) && (*inpt != '\0')) {			if (prnt)				warn(1,"Replacement name too long %s >> %s",				    name, nname);			return(1);		} 		/*		 * inform the user of the result if wanted		 */		if (prnt && (pt->flgs & PRNT)) {			if (*nname == '\0')				(void)fprintf(stderr,"%s >> <empty string>\n",				    name);			else 				(void)fprintf(stderr,"%s >> %s\n", name, nname);		}		/*		 * if empty inform the caller this file is to be skipped		 * otherwise copy the new name over the orig name and return		 */		if (*nname == '\0') 			return(1);		*nlen = l_strncpy(name, nname, PAXPATHLEN + 1);	}	return(0);}#ifdef NET2_REGEX/* * resub() *	apply the replacement to the matched expression. expand out the old * 	style ed(1) subexpression expansion. * Return: *	-1 if error, or the number of characters added to the destination. */#if __STDC__static intresub(regexp *prog, char *src, char *dest, register char *destend)#elsestatic intresub(prog, src, dest, destend)	regexp *prog;	char *src;	char *dest;	register char *destend;#endif{	register char *spt;	register char *dpt;	register char c;	register int no;	register int len;	spt = src;	dpt = dest;	while ((dpt < destend) && ((c = *spt++) != '\0')) {		if (c == '&')			no = 0;		else if ((c == '\\') && (*spt >= '0') && (*spt <= '9'))			no = *spt++ - '0';		else { 			if ((c == '\\') && ((*spt == '\\') || (*spt == '&'))) 				c = *spt++; 			*dpt++ = c;			continue;		} 		if ((prog->startp[no] == NULL) || (prog->endp[no] == NULL) ||		    ((len = prog->endp[no] - prog->startp[no]) <= 0))			continue;		/*		 * copy the subexpression to the destination.		 * fail if we run out of space or the match string is damaged		 */		if (len > (destend - dpt))			len = destend - dpt;		if (l_strncpy(dpt, prog->startp[no], len) != len)			return(-1);		dpt += len;	}	return(dpt - dest);}#else/* * resub() *	apply the replacement to the matched expression. expand out the old * 	style ed(1) subexpression expansion. * Return: *	-1 if error, or the number of characters added to the destination. */#if __STDC__static intresub(regex_t *rp, register regmatch_t *pm, char *src, char *dest,	register char *destend)#elsestatic intresub(rp, pm, src, dest, destend)	regex_t *rp;	register regmatch_t *pm;	char *src;	char *dest;	register char *destend;#endif{	register char *spt;	register char *dpt;	register char c;	register regmatch_t *pmpt;	register int len;	int subexcnt;	spt =  src;	dpt = dest;	subexcnt = rp->re_nsub;	while ((dpt < destend) && ((c = *spt++) != '\0')) {		/*		 * see if we just have an ordinary replacement character		 * or we refer to a subexpression.		 */		if (c == '&') {			pmpt = pm;		} else if ((c == '\\') && (*spt >= '0') && (*spt <= '9')) {			/*			 * make sure there is a subexpression as specified			 */			if ((len = *spt++ - '0') > subexcnt)				return(-1);			pmpt = pm + len;		} else { 			/*			 * Ordinary character, just copy it			 */ 			if ((c == '\\') && ((*spt == '\\') || (*spt == '&'))) 				c = *spt++; 			*dpt++ = c;			continue;		}		/*		 * continue if the subexpression is bogus		 */		if ((pmpt->rm_so < 0) || (pmpt->rm_eo < 0) ||		    ((len = pmpt->rm_eo - pmpt->rm_so) <= 0))			continue;		/*		 * copy the subexpression to the destination.		 * fail if we run out of space or the match string is damaged		 */		if (len > (destend - dpt))			len = destend - dpt;		if (l_strncpy(dpt, src + pmpt->rm_so, len) != len)			return(-1);		dpt += len;	}	return(dpt - dest);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -