Refactor tar(1)

This commit is contained in:
FRIGN 2015-02-16 19:47:36 +01:00
parent bec3c32dbd
commit eb17f2cc9c

105
tar.c
View File

@ -11,8 +11,7 @@
#include "util.h" #include "util.h"
typedef struct Header Header; struct header {
struct Header {
char name[100]; char name[100];
char mode[8]; char mode[8];
char uid[8]; char uid[8];
@ -22,8 +21,8 @@ struct Header {
char chksum[8]; char chksum[8];
char type; char type;
char link[100]; char link[100];
char magic[6]; char *magic;
char version[2]; char *version;
char uname[32]; char uname[32];
char gname[32]; char gname[32];
char major[8]; char major[8];
@ -31,22 +30,13 @@ struct Header {
char prefix[155]; char prefix[155];
}; };
enum { #define BLKSIZ 512
Blksiz = 512
};
enum Type { enum Type {
REG = '0', AREG = '\0', HARDLINK = '1', SYMLINK = '2', CHARDEV = '3', REG = '0', AREG = '\0', HARDLINK = '1', SYMLINK = '2', CHARDEV = '3',
BLOCKDEV = '4', DIRECTORY = '5', FIFO = '6' BLOCKDEV = '4', DIRECTORY = '5', FIFO = '6'
}; };
static void putoctal(char *, unsigned, int);
static int archive(const char *);
static int unarchive(char *, int, char[Blksiz]);
static int print(char *, int , char[Blksiz]);
static void c(const char *, int);
static void xt(int (*)(char*, int, char[Blksiz]));
static FILE *tarfile; static FILE *tarfile;
static ino_t tarinode; static ino_t tarinode;
static dev_t tardev; static dev_t tardev;
@ -58,16 +48,16 @@ static char filtermode;
static FILE * static FILE *
decomp(FILE *fp) decomp(FILE *fp)
{ {
int fds[2];
pid_t pid; pid_t pid;
int fds[2];
if (pipe(fds) < 0) if (pipe(fds) < 0)
eprintf("pipe:"); eprintf("pipe:");
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0)
eprintf("fork:"); eprintf("fork:");
} else if (!pid) { else if (!pid) {
dup2(fileno(fp), 0); dup2(fileno(fp), 0);
dup2(fds[1], 1); dup2(fds[1], 1);
close(fds[0]); close(fds[0]);
@ -83,7 +73,6 @@ decomp(FILE *fp)
break; break;
} }
} }
close(fds[1]); close(fds[1]);
return fdopen(fds[0], "r"); return fdopen(fds[0], "r");
} }
@ -91,21 +80,20 @@ decomp(FILE *fp)
static void static void
putoctal(char *dst, unsigned num, int n) putoctal(char *dst, unsigned num, int n)
{ {
snprintf(dst, n, "%.*o", n-1, num); snprintf(dst, n, "%.*o", n - 1, num);
} }
static int static int
archive(const char* path) archive(const char* path)
{ {
unsigned char b[Blksiz]; FILE *f;
unsigned chksum;
int l, x;
Header *h = (void*)b;
FILE *f = NULL;
struct stat st;
struct passwd *pw;
struct group *gr;
mode_t mode; mode_t mode;
struct group *gr;
struct header *h;
struct passwd *pw;
struct stat st;
size_t chksum, l, x;
unsigned char b[BLKSIZ];
lstat(path, &st); lstat(path, &st);
if (st.st_ino == tarinode && st.st_dev == tardev) { if (st.st_ino == tarinode && st.st_dev == tardev) {
@ -115,15 +103,16 @@ archive(const char* path)
pw = getpwuid(st.st_uid); pw = getpwuid(st.st_uid);
gr = getgrgid(st.st_gid); gr = getgrgid(st.st_gid);
memset(b, 0, sizeof b); h = (void*)b;
snprintf(h->name, sizeof h->name, "%s", path); memset(b, 0, sizeof(b));
putoctal(h->mode, (unsigned)st.st_mode&0777, sizeof h->mode); snprintf(h->name, sizeof(h->name), "%s", path);
putoctal(h->uid, (unsigned)st.st_uid, sizeof h->uid); putoctal(h->mode, (unsigned)st.st_mode & 0777, sizeof(h->mode));
putoctal(h->gid, (unsigned)st.st_gid, sizeof h->gid); putoctal(h->uid, (unsigned)st.st_uid, sizeof(h->uid));
putoctal(h->size, 0, sizeof h->size); putoctal(h->gid, (unsigned)st.st_gid, sizeof(h->gid));
putoctal(h->mtime, (unsigned)st.st_mtime, sizeof h->mtime); putoctal(h->size, 0, sizeof(h->size));
memcpy(h->magic, "ustar", sizeof h->magic); putoctal(h->mtime, (unsigned)st.st_mtime, sizeof(h->mtime));
memcpy(h->version, "00", sizeof h->version); h->magic = "ustar";
h->version = "00";
snprintf(h->uname, sizeof h->uname, "%s", pw ? pw->pw_name : ""); snprintf(h->uname, sizeof h->uname, "%s", pw ? pw->pw_name : "");
snprintf(h->gname, sizeof h->gname, "%s", gr ? gr->gr_name : ""); snprintf(h->gname, sizeof h->gname, "%s", gr ? gr->gr_name : "");
@ -154,26 +143,26 @@ archive(const char* path)
chksum += b[x]; chksum += b[x];
putoctal(h->chksum, chksum, sizeof h->chksum); putoctal(h->chksum, chksum, sizeof h->chksum);
fwrite(b, Blksiz, 1, tarfile); fwrite(b, BLKSIZ, 1, tarfile);
if (!f) if (!f)
return 0; return 0;
while ((l = fread(b, 1, Blksiz, f)) > 0) { while ((l = fread(b, 1, BLKSIZ, f)) > 0) {
if (l < Blksiz) if (l < BLKSIZ)
memset(b+l, 0, Blksiz-l); memset(b+l, 0, BLKSIZ-l);
fwrite(b, Blksiz, 1, tarfile); fwrite(b, BLKSIZ, 1, tarfile);
} }
fclose(f); fclose(f);
return 0; return 0;
} }
static int static int
unarchive(char *fname, int l, char b[Blksiz]) unarchive(char *fname, int l, char b[BLKSIZ])
{ {
char lname[101];
FILE *f = NULL; FILE *f = NULL;
unsigned long mode, major, minor, type, mtime;
struct timeval times[2]; struct timeval times[2];
Header *h = (void*)b; struct header *h = (void*)b;
unsigned long mode, major, minor, type, mtime;
char lname[101];
if (!mflag) if (!mflag)
mtime = strtoul(h->mtime, 0, 8); mtime = strtoul(h->mtime, 0, 8);
@ -215,12 +204,11 @@ unarchive(char *fname, int l, char b[Blksiz])
default: default:
fprintf(stderr, "usupported tarfiletype %c\n", h->type); fprintf(stderr, "usupported tarfiletype %c\n", h->type);
} }
if (getuid() == 0 && chown(fname, strtoul(h->uid, 0, 8), if (getuid() == 0 && chown(fname, strtoul(h->uid, 0, 8), strtoul(h->gid, 0, 8)))
strtoul(h->gid, 0, 8)))
perror(fname); perror(fname);
for (; l > 0; l -= Blksiz) { for (; l > 0; l -= BLKSIZ) {
fread(b, Blksiz, 1, tarfile); fread(b, BLKSIZ, 1, tarfile);
if (f) if (f)
fwrite(b, MIN(l, 512), 1, f); fwrite(b, MIN(l, 512), 1, f);
} }
@ -237,11 +225,11 @@ unarchive(char *fname, int l, char b[Blksiz])
} }
static int static int
print(char * fname, int l, char b[Blksiz]) print(char * fname, int l, char b[BLKSIZ])
{ {
puts(fname); puts(fname);
for (; l > 0; l -= Blksiz) for (; l > 0; l -= BLKSIZ)
fread(b, Blksiz, 1, tarfile); fread(b, BLKSIZ, 1, tarfile);
return 0; return 0;
} }
@ -253,12 +241,12 @@ c(const char * path, int fflag)
} }
static void static void
xt(int (*fn)(char*, int, char[Blksiz])) xt(int (*fn)(char*, int, char[BLKSIZ]))
{ {
char b[Blksiz], fname[257], *s; char b[BLKSIZ], fname[257], *s;
Header *h = (void*)b; struct header *h = (void*)b;
while (fread(b, Blksiz, 1, tarfile) && h->name[0] != '\0') { while (fread(b, BLKSIZ, 1, tarfile) && h->name[0] != '\0') {
s = fname; s = fname;
if (h->prefix[0] != '\0') if (h->prefix[0] != '\0')
s += sprintf(s, "%.*s/", (int)sizeof h->prefix, h->prefix); s += sprintf(s, "%.*s/", (int)sizeof h->prefix, h->prefix);
@ -277,10 +265,9 @@ usage(void)
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
struct stat st;
char *file = NULL, *dir = ".";
char mode = '\0';
FILE *fp; FILE *fp;
struct stat st;
char *file = NULL, *dir = ".", mode = '\0';
ARGBEGIN { ARGBEGIN {
case 'x': case 'x':