📄 tar.c
字号:
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 + -