📄 untgz.c
字号:
/* * untgz.c -- Display contents and extract files from a gzip'd TAR file * * written by Pedro A. Aranda Gutierrez <paag@tid.es> * adaptation to Unix by Jean-loup Gailly <jloup@gzip.org> * various fixes by Cosmin Truta <cosmint@cs.ubbcluj.ro> */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <errno.h>#include "zlib.h"#ifdef unix# include <unistd.h>#else# include <direct.h># include <io.h>#endif#ifdef WIN32#include <windows.h># ifndef F_OK# define F_OK 0# endif# define mkdir(dirname,mode) _mkdir(dirname)# ifdef _MSC_VER# define access(path,mode) _access(path,mode)# define chmod(path,mode) _chmod(path,mode)# define strdup(str) _strdup(str)# endif#else# include <utime.h>#endif/* values used in typeflag field */#define REGTYPE '0' /* regular file */#define AREGTYPE '\0' /* regular file */#define LNKTYPE '1' /* link */#define SYMTYPE '2' /* reserved */#define CHRTYPE '3' /* character special */#define BLKTYPE '4' /* block special */#define DIRTYPE '5' /* directory */#define FIFOTYPE '6' /* FIFO special */#define CONTTYPE '7' /* reserved *//* GNU tar extensions */#define GNUTYPE_DUMPDIR 'D' /* file names from dumped directory */#define GNUTYPE_LONGLINK 'K' /* long link name */#define GNUTYPE_LONGNAME 'L' /* long file name */#define GNUTYPE_MULTIVOL 'M' /* continuation of file from another volume */#define GNUTYPE_NAMES 'N' /* file name that does not fit into main hdr */#define GNUTYPE_SPARSE 'S' /* sparse file */#define GNUTYPE_VOLHDR 'V' /* tape/volume header *//* tar header */#define BLOCKSIZE 512#define SHORTNAMESIZE 100struct tar_header{ /* byte offset */ char name[100]; /* 0 */ char mode[8]; /* 100 */ char uid[8]; /* 108 */ char gid[8]; /* 116 */ char size[12]; /* 124 */ char mtime[12]; /* 136 */ char chksum[8]; /* 148 */ char typeflag; /* 156 */ char linkname[100]; /* 157 */ char magic[6]; /* 257 */ char version[2]; /* 263 */ char uname[32]; /* 265 */ char gname[32]; /* 297 */ char devmajor[8]; /* 329 */ char devminor[8]; /* 337 */ char prefix[155]; /* 345 */ /* 500 */};union tar_buffer{ char buffer[BLOCKSIZE]; struct tar_header header;};struct attr_item{ struct attr_item *next; char *fname; int mode; time_t time;};enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID };char *TGZfname OF((const char *));void TGZnotfound OF((const char *));int getoct OF((char *, int));char *strtime OF((time_t *));int setfiletime OF((char *, time_t));void push_attr OF((struct attr_item **, char *, int, time_t));void restore_attr OF((struct attr_item **));int ExprMatch OF((char *, char *));int makedir OF((char *));int matchname OF((int, int, char **, char *));void error OF((const char *));int tar OF((gzFile, int, int, int, char **));void help OF((int));int main OF((int, char **));char *prog;const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL };/* return the file name of the TGZ archive *//* or NULL if it does not exist */char *TGZfname (const char *arcname){ static char buffer[1024]; int origlen,i; strcpy(buffer,arcname); origlen = strlen(buffer); for (i=0; TGZsuffix[i]; i++) { strcpy(buffer+origlen,TGZsuffix[i]); if (access(buffer,F_OK) == 0) return buffer; } return NULL;}/* error message for the filename */void TGZnotfound (const char *arcname){ int i; fprintf(stderr,"%s: Couldn't find ",prog); for (i=0;TGZsuffix[i];i++) fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n", arcname, TGZsuffix[i]); exit(1);}/* convert octal digits to int *//* on error return -1 */int getoct (char *p,int width){ int result = 0; char c; while (width--) { c = *p++; if (c == 0) break; if (c == ' ') continue; if (c < '0' || c > '7') return -1; result = result * 8 + (c - '0'); } return result;}/* convert time_t to string *//* use the "YYYY/MM/DD hh:mm:ss" format */char *strtime (time_t *t){ struct tm *local; static char result[32]; local = localtime(t); sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d", local->tm_year+1900, local->tm_mon+1, local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec); return result;}/* set file time */int setfiletime (char *fname,time_t ftime){#ifdef WIN32 static int isWinNT = -1; SYSTEMTIME st; FILETIME locft, modft; struct tm *loctm; HANDLE hFile; int result; loctm = localtime(&ftime); if (loctm == NULL) return -1; st.wYear = (WORD)loctm->tm_year + 1900; st.wMonth = (WORD)loctm->tm_mon + 1; st.wDayOfWeek = (WORD)loctm->tm_wday; st.wDay = (WORD)loctm->tm_mday; st.wHour = (WORD)loctm->tm_hour; st.wMinute = (WORD)loctm->tm_min; st.wSecond = (WORD)loctm->tm_sec; st.wMilliseconds = 0; if (!SystemTimeToFileTime(&st, &locft) || !LocalFileTimeToFileTime(&locft, &modft)) return -1; if (isWinNT < 0) isWinNT = (GetVersion() < 0x80000000) ? 1 : 0; hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0), NULL); if (hFile == INVALID_HANDLE_VALUE) return -1; result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1; CloseHandle(hFile); return result;#else struct utimbuf settime; settime.actime = settime.modtime = ftime; return utime(fname,&settime);#endif}/* push file attributes */void push_attr(struct attr_item **list,char *fname,int mode,time_t time){ struct attr_item *item; item = (struct attr_item *)malloc(sizeof(struct attr_item)); if (item == NULL) error("Out of memory"); item->fname = strdup(fname); item->mode = mode; item->time = time; item->next = *list; *list = item;}/* restore file attributes */void restore_attr(struct attr_item **list){ struct attr_item *item, *prev; for (item = *list; item != NULL; ) { setfiletime(item->fname,item->time); chmod(item->fname,item->mode); prev = item; item = item->next; free(prev); } *list = NULL;}/* match regular expression */#define ISSPECIAL(c) (((c) == '*') || ((c) == '/'))int ExprMatch (char *string,char *expr){ while (1) { if (ISSPECIAL(*expr)) { if (*expr == '/') { if (*string != '\\' && *string != '/') return 0; string ++; expr++; } else if (*expr == '*') { if (*expr ++ == 0) return 1; while (*++string != *expr) if (*string == 0) return 0; } } else { if (*string != *expr) return 0; if (*expr++ == 0) return 1; string++; } }}/* recursive mkdir *//* abort on ENOENT; ignore other errors like "directory already exists" *//* return 1 if OK *//* 0 on error */int makedir (char *newdir){ char *buffer = strdup(newdir); char *p; int len = strlen(buffer); if (len <= 0) { free(buffer); return 0; } if (buffer[len-1] == '/') {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -