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

📄 tar.c

📁 unix 下tar 执行程序的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
addname(name)
	char	*name;			/* pointer to name */
{
	register int	i;		/* Length of string */
	register struct name	*p;	/* Current struct pointer */
	static char *chdir_name;
	char *new_name();
#define MAXPATHLEN 1024

	if(name[0]=='-' && name[1]=='C' && name[2]=='\0') {
		chdir_name=name_next(0);
		name=name_next(0);
		if(!chdir_name) {
			msg("Missing file name after -C");
			exit(EX_ARGSBAD);
		}
		if(chdir_name[0]!='/') {
			char path[MAXPATHLEN];
#if defined(MSDOS) || defined(USG)
			int getcwd();

			if(!getcwd(path,MAXPATHLEN))
				msg("Couldn't get current directory.");
				exit(EX_SYSTEM);
#else
			char *getwd();

			if(!getwd(path)) {
				msg("Couldn't get current directory: %s",path);
				exit(EX_SYSTEM);
			}
#endif
			chdir_name=new_name(path,chdir_name);
		}
	}

	if (name)
	  {
	    i = strlen(name);
	    /*NOSTRICT*/
	    p = (struct name *)malloc((unsigned)(sizeof(struct name) + i));
	  }
	else
	  p = (struct name *)malloc ((unsigned)(sizeof (struct name)));
	if (!p) {
	  if (name)
	    msg("cannot allocate mem for name '%s'.",name);
	  else
	    msg("cannot allocate mem for chdir record.");
	  exit(EX_SYSTEM);
	}
	p->next = (struct name *)NULL;
	if (name)
	  {
	    p->fake = 0;
	    p->length = i;
	    strncpy(p->name, name, i);
	    p->name[i] = '\0';	/* Null term */
	  }
	else
	  p->fake = 1;
	p->found = 0;
	p->regexp = 0;		/* Assume not a regular expression */
	p->firstch = 1;		/* Assume first char is literal */
	p->change_dir=chdir_name;
	p->dir_contents = 0;	/* JF */
	if (name)
	  {
	    if (index(name, '*') || index(name, '[') || index(name, '?')) {
	      p->regexp = 1;	/* No, it's a regexp */
	      if (name[0] == '*' || name[0] == '[' || name[0] == '?')
		p->firstch = 0;		/* Not even 1st char literal */
	    }
	  }

	if (namelast) namelast->next = p;
	namelast = p;
	if (!namelist) namelist = p;
}
/*
 * Match a name from an archive, p, with a name from the namelist.
 */
name_match(p)
	register char *p;
{
	register struct name	*nlp;
	register int		len;

again:
	if (0 == (nlp = namelist))	/* Empty namelist is easy */
		return 1;
	if (nlp->fake)
	  {
	    if (nlp->change_dir && chdir (nlp->change_dir))
	      msg_perror ("Can't change to directory %d", nlp->change_dir);
	    namelist = 0;
	    return 1;
	  }
	len = strlen(p);
	for (; nlp != 0; nlp = nlp->next) {
		/* If first chars don't match, quick skip */
		if (nlp->firstch && nlp->name[0] != p[0])
			continue;

		/* Regular expressions */
		if (nlp->regexp) {
			if (wildmat(p, nlp->name)) {
				nlp->found = 1;	/* Remember it matched */
				if(f_startfile) {
					free((void *)namelist);
					namelist=0;
				}
				if(nlp->change_dir && chdir(nlp->change_dir))
					msg_perror("Can't change to directory %s",nlp->change_dir);
				return 1;	/* We got a match */
			}
			continue;
		}

		/* Plain Old Strings */
		if (nlp->length <= len		/* Archive len >= specified */
		 && (p[nlp->length] == '\0' || p[nlp->length] == '/')
						/* Full match on file/dirname */
		 && strncmp(p, nlp->name, nlp->length) == 0) /* Name compare */
		{
			nlp->found = 1;		/* Remember it matched */
			if(f_startfile) {
				free((void *)namelist);
				namelist = 0;
			}
			if(nlp->change_dir && chdir(nlp->change_dir))
				msg_perror("Can't change to directory %s",nlp->change_dir);
			return 1;		/* We got a match */
		}
	}

	/*
	 * Filename from archive not found in namelist.
	 * If we have the whole namelist here, just return 0.
	 * Otherwise, read the next name in and compare it.
	 * If this was the last name, namelist->found will remain on.
	 * If not, we loop to compare the newly read name.
	 */
	if (f_sorted_names && namelist->found) {
		name_gather();		/* Read one more */
		if (!namelist->found) goto again;
	}
	return 0;
}


/*
 * Print the names of things in the namelist that were not matched.
 */
names_notfound()
{
	register struct name	*nlp,*next;
	register char		*p;

	for (nlp = namelist; nlp != 0; nlp = next) {
		next=nlp->next;
		if (!nlp->found)
			msg("%s not found in archive",nlp->name);

		/*
		 * We could free() the list, but the process is about
		 * to die anyway, so save some CPU time.  Amigas and
		 * other similarly broken software will need to waste
		 * the time, though.
		 */
#ifndef unix
		if (!f_sorted_names)
			free(nlp);
#endif
	}
	namelist = (struct name *)NULL;
	namelast = (struct name *)NULL;

	if (f_sorted_names) {
		while (0 != (p = name_next(1)))
			msg("%s not found in archive", p);
	}
}

/* These next routines were created by JF */

name_expand()
{
;
}

/* This is like name_match(), except that it returns a pointer to the name
   it matched, and doesn't set ->found  The caller will have to do that
   if it wants to.  Oh, and if the namelist is empty, it returns 0, unlike
   name_match(), which returns TRUE */

struct name *
name_scan(p)
register char *p;
{
	register struct name	*nlp;
	register int		len;

again:
	if (0 == (nlp = namelist))	/* Empty namelist is easy */
		return 0;
	len = strlen(p);
	for (; nlp != 0; nlp = nlp->next) {
		/* If first chars don't match, quick skip */
		if (nlp->firstch && nlp->name[0] != p[0])
			continue;

		/* Regular expressions */
		if (nlp->regexp) {
			if (wildmat(p, nlp->name))
				return nlp;	/* We got a match */
			continue;
		}

		/* Plain Old Strings */
		if (nlp->length <= len		/* Archive len >= specified */
		 && (p[nlp->length] == '\0' || p[nlp->length] == '/')
						/* Full match on file/dirname */
		 && strncmp(p, nlp->name, nlp->length) == 0) /* Name compare */
			return nlp;		/* We got a match */
	}

	/*
	 * Filename from archive not found in namelist.
	 * If we have the whole namelist here, just return 0.
	 * Otherwise, read the next name in and compare it.
	 * If this was the last name, namelist->found will remain on.
	 * If not, we loop to compare the newly read name.
	 */
	if (f_sorted_names && namelist->found) {
		name_gather();		/* Read one more */
		if (!namelist->found) goto again;
	}
	return (struct name *) 0;
}

/* This returns a name from the namelist which doesn't have ->found set.
   It sets ->found before returning, so successive calls will find and return
   all the non-found names in the namelist */

struct name *gnu_list_name;

char *
name_from_list()
{
	if(!gnu_list_name)
		gnu_list_name = namelist;
	while(gnu_list_name && gnu_list_name->found)
		gnu_list_name=gnu_list_name->next;
	if(gnu_list_name) {
		gnu_list_name->found++;
		if(gnu_list_name->change_dir)
			if(chdir(gnu_list_name->change_dir)<0)
				msg_perror("can't chdir to %s",gnu_list_name->change_dir);
		return gnu_list_name->name;
	}
	return (char *)0;
}

blank_name_list()
{
	struct name *n;

	gnu_list_name = 0;
	for(n=namelist;n;n=n->next)
		n->found = 0;
}

char *
new_name(path,name)
char *path,*name;
{
	char *path_buf;

	path_buf=(char *)malloc(strlen(path)+strlen(name)+2);
	if(path_buf==0) {
		msg("Can't allocate memory for name '%s/%s",path,name);
		exit(EX_SYSTEM);
	}
	(void) sprintf(path_buf,"%s/%s",path,name);
	return path_buf;
}

/* returns non-zero if the luser typed 'y' or 'Y', zero otherwise. */

int
confirm(action,file)
char *action, *file;
{
	int	c,nl;
	static FILE *confirm_file = 0;
	extern FILE *msg_file;
	extern char TTY_NAME[];

	fprintf(msg_file,"%s %s?", action, file);
	fflush(msg_file);
	if(!confirm_file) {
		confirm_file = (archive == 0) ? fopen(TTY_NAME, "r") : stdin;
		if(!confirm_file) {
			msg("Can't read confirmation from user");
			exit(EX_SYSTEM);
		}
	}
	c=getc(confirm_file);
	for(nl = c; nl != '\n' && nl != EOF; nl = getc(confirm_file))
		;
	return (c=='y' || c=='Y');
}

char *x_buffer = 0;
int size_x_buffer;
int free_x_buffer;

char **exclude = 0;
int size_exclude = 0;
int free_exclude = 0;

char **re_exclude = 0;
int size_re_exclude = 0;
int free_re_exclude = 0;

add_exclude(name)
char *name;
{
	char *rname;
	char **tmp_ptr;
	int size_buf;

	un_quote_string(name);
	size_buf = strlen(name);

	if(x_buffer==0) {
		x_buffer = (char *)ck_malloc(size_buf+1024);
		free_x_buffer=1024;
	} else if(free_x_buffer<=size_buf) {
		char *old_x_buffer;
		char **tmp_ptr;

		old_x_buffer = x_buffer;
		x_buffer = (char *)ck_realloc(x_buffer,size_x_buffer+1024);
		free_x_buffer = 1024;
		for(tmp_ptr=exclude;tmp_ptr<exclude+size_exclude;tmp_ptr++)
			*tmp_ptr= x_buffer + ((*tmp_ptr) - old_x_buffer);
		for(tmp_ptr=re_exclude;tmp_ptr<re_exclude+size_re_exclude;tmp_ptr++)
			*tmp_ptr= x_buffer + ((*tmp_ptr) - old_x_buffer);
	}

	if(is_regex(name)) {
		if(free_re_exclude==0) {
			re_exclude= (char **)(re_exclude ? ck_realloc(re_exclude,(size_re_exclude+32)*sizeof(char *)) : ck_malloc(sizeof(char *)*32));
			free_re_exclude+=32;
		}
		re_exclude[size_re_exclude]=x_buffer+size_x_buffer;
		size_re_exclude++;
		free_re_exclude--;
	} else {
		if(free_exclude==0) {
			exclude=(char **)(exclude ? ck_realloc(exclude,(size_exclude+32)*sizeof(char *)) : ck_malloc(sizeof(char *)*32));
			free_exclude+=32;
		}
		exclude[size_exclude]=x_buffer+size_x_buffer;
		size_exclude++;
		free_exclude--;
	}
	strcpy(x_buffer+size_x_buffer,name);
	size_x_buffer+=size_buf+1;
	free_x_buffer-=size_buf+1;
}

add_exclude_file(file)
char *file;
{
	FILE *fp;
	char buf[1024];
	extern char *rindex();

	if(strcmp(file, "-"))
		fp=fopen(file,"r");
	else
		/* Let's hope the person knows what they're doing. */
		/* Using -X - -T - -f - will get you *REALLY* strange
		   results. . . */
		fp=stdin;

	if(!fp) {
		msg_perror("can't open %s",file);
		exit(2);
	}
	while(fgets(buf,1024,fp)) {
		int size_buf;
		char *end_str;

		end_str=rindex(buf,'\n');
		if(end_str)
			*end_str='\0';
		add_exclude(buf);

	}
	fclose(fp);
}

int
is_regex(str)
char *str;
{
	return index(str,'*') || index(str,'[') || index(str,'?');
}

/* Returns non-zero if the file 'name' should not be added/extracted */
int
check_exclude(name)
char *name;
{
	int n;
	char *str;
	extern char *strstr();

	for(n=0;n<size_re_exclude;n++) {
		if(wildmat(name,re_exclude[n]))
			return 1;
	}
	for(n=0;n<size_exclude;n++) {
		/* Accept the output from strstr only if it is the last
		   part of the string.  There is certainly a faster way to
		   do this. . . */
		if(   (str=strstr(name,exclude[n]))
 		   && (str==name || str[-1]=='/')
		   && str[strlen(exclude[n])]=='\0')
			return 1;
	}
	return 0;
}

⌨️ 快捷键说明

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