#include #include #include "detar.h" extern char *tbuf; static union record tar_rec; static struct s_q { char name[NAMSIZ]; char link[NAMSIZ]; int mode,linkflag; long size; }my_header; static struct link_q { struct link_q *prev; char name[NAMSIZ]; char link[NAMSIZ]; }*link_list,*new_link,*todo_link; extern long from_oct(); extern int chec_chksum(); extern int nodev, nopath, tfile, xtract, type, verbos; extern FILE *ftar; extern char *to_gem(); static int read_header() { int chk; do { if(tfile) { fread(tar_rec.charptr,1,RECORDSIZE,ftar); if(feof(ftar))return -1; } else { tread(tar_rec.charptr,RECORDSIZE); if(!tar_rec.charptr[0]) return -1; } chk=chec_chksum(&tar_rec); }while(chk==2); return chk; } do_detar(test)int (*test)(); { int chk; long fsiz; char *p; extern char *index(), *rindex(); link_list=NULL; while((chk=read_header())>=0) { if((Crawio(255) & 0xff) == 3) { fprintf(stderr, "User interrupt, Aborting\n"); if(tfile) fclose(ftar); else tclose(); Exit(1); } if(chk==0) { fprintf(stderr, "Checksum error on %s aborting",tar_rec.header.name); Exit(2); } if(tar_rec.header.name[strlen(tar_rec.header.name)-1]=='/') { tar_rec.header.name[strlen(tar_rec.header.name)-1]='\0'; my_header.linkflag=LF_DIR; } else my_header.linkflag=tar_rec.header.linkflag; strcpy(my_header.name,to_gem(tar_rec.header.name)); strcpy(my_header.link,to_gem(tar_rec.header.linkname)); my_header.size=from_oct(12,tar_rec.header.size); if(!(*test)(my_header.name)) { if(!tfile) { if(tspace(my_header.size)) Exit(1); } else { for(fsiz = 0L; fsiz < my_header.size; fsiz += 512L) { fread(tar_rec.charptr,1,RECORDSIZE,ftar); if(feof(ftar))return -1; } } continue; } switch(my_header.linkflag) { case LF_OLDNORMAL: case LF_NORMAL: case LF_CHR: case LF_BLK: case LF_FIFO: case LF_CONTIG: { FILE *fout; int n; long mtime; if(xtract) { if(nodev) { p = index(my_header.name, ':') + 2; if(p) sprintf(my_header.name, "%s", p); } if(nopath) { p = rindex(my_header.name, '\\') + 1; if(p) sprintf(my_header.name, "%s", p); } Makedirs(my_header.name); if((fout=fopen(my_header.name, "wb"))==NULL) { fprintf(stderr,"tar:Can't open %s\n", my_header.name); Exit(3); } } if(type || verbos) { mtime=from_oct(12,tar_rec.header.mtime); if(xtract) printf("x "); n=from_oct(8,tar_rec.header.mode); vtype(n, my_header.size, mtime, my_header.name); if(!xtract) { if(!tfile) { if(tspace(my_header.size)) Exit(1); } else { for(mtime = 0L; mtime < my_header.size; mtime += 512L) { fread(tar_rec.charptr,1,RECORDSIZE,ftar); if(feof(ftar))return -1; } } break; } } while(my_header.size >0) { if(tfile) fread(tar_rec.charptr,1,RECORDSIZE,ftar); else tread(tar_rec.charptr,RECORDSIZE); n=(my_header.size>RECORDSIZE)?RECORDSIZE: (int)my_header.size; if(xtract) fwrite(tar_rec.charptr,1,n,fout); else { for(n = 100; n > 0; n--); } my_header.size = my_header.size - RECORDSIZE; } if(xtract) { fclose(fout); } break; } case LF_LINK: case LF_SYMLINK: new_link=(struct link_q *)malloc(sizeof(struct link_q)); new_link->prev=link_list; strcpy(new_link->name,my_header.name); strcpy(new_link->link,my_header.link); link_list=new_link; break; case LF_DIR: if(xtract && !nopath) { if(nodev) { p = index(my_header.name, ':') + 2; if(p) sprintf(my_header.name, "%s", p); } mkdir(my_header.name); } break; } } do { todo_link=NULL; while(link_list) { struct stat stbuf; new_link=link_list; link_list=new_link->prev; if(stat(new_link->link,&stbuf)) { new_link->prev=todo_link; todo_link=new_link; } else { FILE *fin,*fout; int n; if(xtract) { Makedirs(new_link->name); if((fin=fopen(new_link->link,"rb"))==NULL) { fprintf(stderr, "tar: Cant open %s for copying\n", new_link->link); Exit(3); } if((fout=fopen(new_link->name,"wb"))==NULL) { fprintf(stderr, "tar: Can't open %s to copy to\n", new_link->name); Exit(3); } for(n=RECORDSIZE;n;) { n=fread(tar_rec.charptr,1,RECORDSIZE, fin); fwrite(tar_rec.charptr,1,n,fout); } fclose(fin); fclose(fout); free(new_link); } } } link_list=todo_link; }while(todo_link); }