📄 untgz.c
字号:
buffer[len-1] = '\0';
}
if (mkdir(buffer, 0755) == 0)
{
free(buffer);
return 1;
}
p = buffer+1;
while (1)
{
char hold;
while(*p && *p != '\\' && *p != '/')
p++;
hold = *p;
*p = 0;
if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT))
{
fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer);
free(buffer);
return 0;
}
if (hold == 0)
break;
*p++ = hold;
}
free(buffer);
return 1;
}
int matchname (int arg,int argc,char **argv,char *fname)
{
if (arg == argc) /* no arguments given (untgz tgzarchive) */
return 1;
while (arg < argc)
if (ExprMatch(fname,argv[arg++]))
return 1;
return 0; /* ignore this for the moment being */
}
/* tar file list or extract */
int tar (gzFile in,int action,int arg,int argc,char **argv)
{
union tar_buffer buffer;
int len;
int err;
int getheader = 1;
int remaining = 0;
FILE *outfile = NULL;
char fname[BLOCKSIZE];
int tarmode;
time_t tartime;
struct attr_item *attributes = NULL;
if (action == TGZ_LIST)
printf(" date time size file\n"
" ---------- -------- --------- -------------------------------------\n");
while (1)
{
len = gzread(in, &buffer, BLOCKSIZE);
if (len < 0)
error(gzerror(in, &err));
/*
* Always expect complete blocks to process
* the tar information.
*/
if (len != BLOCKSIZE)
{
action = TGZ_INVALID; /* force error exit */
remaining = 0; /* force I/O cleanup */
}
/*
* If we have to get a tar header
*/
if (getheader >= 1)
{
/*
* if we met the end of the tar
* or the end-of-tar block,
* we are done
*/
if (len == 0 || buffer.header.name[0] == 0)
break;
tarmode = getoct(buffer.header.mode,8);
tartime = (time_t)getoct(buffer.header.mtime,12);
if (tarmode == -1 || tartime == (time_t)-1)
{
buffer.header.name[0] = 0;
action = TGZ_INVALID;
}
if (getheader == 1)
{
strncpy(fname,buffer.header.name,SHORTNAMESIZE);
if (fname[SHORTNAMESIZE-1] != 0)
fname[SHORTNAMESIZE] = 0;
}
else
{
/*
* The file name is longer than SHORTNAMESIZE
*/
if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0)
error("bad long name");
getheader = 1;
}
/*
* Act according to the type flag
*/
switch (buffer.header.typeflag)
{
case DIRTYPE:
if (action == TGZ_LIST)
printf(" %s <dir> %s\n",strtime(&tartime),fname);
if (action == TGZ_EXTRACT)
{
makedir(fname);
push_attr(&attributes,fname,tarmode,tartime);
}
break;
case REGTYPE:
case AREGTYPE:
remaining = getoct(buffer.header.size,12);
if (remaining == -1)
{
action = TGZ_INVALID;
break;
}
if (action == TGZ_LIST)
printf(" %s %9d %s\n",strtime(&tartime),remaining,fname);
else if (action == TGZ_EXTRACT)
{
if (matchname(arg,argc,argv,fname))
{
outfile = fopen(fname,"wb");
if (outfile == NULL) {
/* try creating directory */
char *p = strrchr(fname, '/');
if (p != NULL) {
*p = '\0';
makedir(fname);
*p = '/';
outfile = fopen(fname,"wb");
}
}
if (outfile != NULL)
printf("Extracting %s\n",fname);
else
fprintf(stderr, "%s: Couldn't create %s",prog,fname);
}
else
outfile = NULL;
}
getheader = 0;
break;
case GNUTYPE_LONGLINK:
case GNUTYPE_LONGNAME:
remaining = getoct(buffer.header.size,12);
if (remaining < 0 || remaining >= BLOCKSIZE)
{
action = TGZ_INVALID;
break;
}
len = gzread(in, fname, BLOCKSIZE);
if (len < 0)
error(gzerror(in, &err));
if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining)
{
action = TGZ_INVALID;
break;
}
getheader = 2;
break;
default:
if (action == TGZ_LIST)
printf(" %s <---> %s\n",strtime(&tartime),fname);
break;
}
}
else
{
unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining;
if (outfile != NULL)
{
if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes)
{
fprintf(stderr,
"%s: Error writing %s -- skipping\n",prog,fname);
fclose(outfile);
outfile = NULL;
remove(fname);
}
}
remaining -= bytes;
}
if (remaining == 0)
{
getheader = 1;
if (outfile != NULL)
{
fclose(outfile);
outfile = NULL;
if (action != TGZ_INVALID)
push_attr(&attributes,fname,tarmode,tartime);
}
}
/*
* Abandon if errors are found
*/
if (action == TGZ_INVALID)
{
error("broken archive");
break;
}
}
/*
* Restore file modes and time stamps
*/
restore_attr(&attributes);
if (gzclose(in) != Z_OK)
error("failed gzclose");
return 0;
}
/* ============================================================ */
void help(int exitval)
{
printf("untgz version 0.2.1\n"
" using zlib version %s\n\n",
zlibVersion());
printf("Usage: untgz file.tgz extract all files\n"
" untgz file.tgz fname ... extract selected files\n"
" untgz -l file.tgz list archive contents\n"
" untgz -h display this help\n");
exit(exitval);
}
void error(const char *msg)
{
fprintf(stderr, "%s: %s\n", prog, msg);
exit(1);
}
/* ============================================================ */
#if defined(WIN32) && defined(__GNUC__)
int _CRT_glob = 0; /* disable argument globbing in MinGW */
#endif
int main(int argc,char **argv)
{
int action = TGZ_EXTRACT;
int arg = 1;
char *TGZfile;
gzFile *f;
prog = strrchr(argv[0],'\\');
if (prog == NULL)
{
prog = strrchr(argv[0],'/');
if (prog == NULL)
{
prog = strrchr(argv[0],':');
if (prog == NULL)
prog = argv[0];
else
prog++;
}
else
prog++;
}
else
prog++;
if (argc == 1)
help(0);
if (strcmp(argv[arg],"-l") == 0)
{
action = TGZ_LIST;
if (argc == ++arg)
help(0);
}
else if (strcmp(argv[arg],"-h") == 0)
{
help(0);
}
if ((TGZfile = TGZfname(argv[arg])) == NULL)
TGZnotfound(argv[arg]);
++arg;
if ((action == TGZ_LIST) && (arg != argc))
help(1);
/*
* Process the TGZ file
*/
switch(action)
{
case TGZ_LIST:
case TGZ_EXTRACT:
f = gzopen(TGZfile,"rb");
if (f == NULL)
{
fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile);
return 1;
}
exit(tar(f, action, arg, argc, argv));
break;
default:
error("Unknown option");
exit(1);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -