/* mangle.c -- encode long filenames Copyright (C) 1988, 1992 Free Software Foundation This file is part of GNU Tar. GNU Tar is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Tar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Tar; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include time_t time(); #include "tar.h" #include "port.h" void add_buffer(); extern PTR ck_malloc(); void finish_header(); extern PTR init_buffer(); extern char *quote_copy_string(); extern char *get_buffer(); char *un_quote_string(); extern union record *start_header(); extern struct stat hstat; /* Stat struct corresponding */ struct mangled { struct mangled *next; int type; char mangled[NAMSIZ]; char *linked_to; char normal[1]; }; /* Should use a hash table, etc. . */ struct mangled *first_mangle; int mangled_num = 0; #if 0 /* Deleted because there is now a better way to do all this */ char * find_mangled (name) char *name; { struct mangled *munge; for(munge=first_mangle;munge;munge=munge->next) if(!strcmp(name,munge->normal)) return munge->mangled; return 0; } #ifdef S_ISLNK void add_symlink_mangle(symlink, linkto, buffer) char *symlink; char *linkto; char *buffer; { struct mangled *munge,*kludge; munge=(struct mangled *)ck_malloc(sizeof(struct mangled)+strlen(symlink)+strlen(linkto)+2); if(!first_mangle) first_mangle=munge; else { for(kludge=first_mangle;kludge->next;kludge=kludge->next) ; kludge->next=munge; } munge->type=1; munge->next=0; strcpy(munge->normal,symlink); munge->linked_to=munge->normal+strlen(symlink)+1; strcpy(munge->linked_to,linkto); sprintf(munge->mangled,"@@MaNgLeD.%d",mangled_num++); strncpy(buffer,munge->mangled,NAMSIZ); } #endif void add_mangle (name, buffer) char *name; char *buffer; { struct mangled *munge,*kludge; munge=(struct mangled *)ck_malloc(sizeof(struct mangled)+strlen(name)); if(!first_mangle) first_mangle=munge; else { for(kludge=first_mangle;kludge->next;kludge=kludge->next) ; kludge->next=munge; } munge->next=0; munge->type=0; strcpy(munge->normal,name); sprintf(munge->mangled,"@@MaNgLeD.%d",mangled_num++); strncpy(buffer,munge->mangled,NAMSIZ); } void write_mangled() { struct mangled *munge; struct stat hstat; union record *header; char *ptr1,*ptr2; PTR the_buffer; int size; int bufsize; if(!first_mangle) return; the_buffer=init_buffer(); for(munge=first_mangle,size=0;munge;munge=munge->next) { ptr1=quote_copy_string(munge->normal); if(!ptr1) ptr1=munge->normal; if(munge->type) { add_buffer(the_buffer,"Symlink ",8); add_buffer(the_buffer,ptr1,strlen(ptr1)); add_buffer(the_buffer," to ",4); if(ptr2=quote_copy_string(munge->linked_to)) { add_buffer(the_buffer,ptr2,strlen(ptr2)); free(ptr2); } else add_buffer(the_buffer,munge->linked_to,strlen(munge->linked_to)); } else { add_buffer(the_buffer,"Rename ",7); add_buffer(the_buffer,munge->mangled,strlen(munge->mangled)); add_buffer(the_buffer," to ",4); add_buffer(the_buffer,ptr1,strlen(ptr1)); } add_buffer(the_buffer,"\n",1); if(ptr1!=munge->normal) free(ptr1); } bzero(&hstat,sizeof(struct stat)); hstat.st_atime=hstat.st_mtime=hstat.st_ctime=time(0); ptr1=get_buffer(the_buffer); hstat.st_size=strlen(ptr1); header=start_header("././@MaNgLeD_NaMeS",&hstat); header->header.linkflag=LF_NAMES; finish_header(header); size=hstat.st_size; header=findrec(); bufsize = endofrecs()->charptr - header->charptr; while(bufsizecharptr,bufsize); ptr1+=bufsize; size-=bufsize; userec(header+(bufsize-1)/RECORDSIZE); header=findrec(); bufsize = endofrecs()->charptr - header->charptr; } bcopy(ptr1,header->charptr,size); bzero(header->charptr+size,bufsize-size); userec(header+(size-1)/RECORDSIZE); } #endif void extract_mangle(head) union record *head; { char *buf; char *fromtape; char *to; char *ptr,*ptrend; char *nam1,*nam1end; int size; int copied; size=hstat.st_size; buf=to=ck_malloc(size+1); buf[size]='\0'; while(size>0) { fromtape=findrec()->charptr; if(fromtape==0) { msg("Unexpected EOF in mangled names!"); return; } copied=endofrecs()->charptr-fromtape; if(copied>size) copied=size; bcopy(fromtape,to,copied); to+=copied; size-=copied; userec((union record *)(fromtape+copied-1)); } for(ptr=buf;*ptr;ptr=ptrend) { ptrend=index(ptr,'\n'); *ptrend++='\0'; if(!strncmp(ptr,"Rename ",7)) { nam1=ptr+7; nam1end=index(nam1,' '); while(strncmp(nam1end," to ",4)) { nam1end++; nam1end=index(nam1end,' '); } *nam1end='\0'; if(ptrend[-2]=='/') ptrend[-2]='\0'; un_quote_string(nam1end+4); if(rename(nam1,nam1end+4)) msg_perror("Can't rename %s to %s",nam1,nam1end+4); else if(f_verbose) msg("Renamed %s to %s",nam1,nam1end+4); } #ifdef S_ISLNK else if(!strncmp(ptr,"Symlink ",8)) { nam1=ptr+8; nam1end=index(nam1,' '); while(strncmp(nam1end," to ",4)) { nam1end++; nam1end=index(nam1end,' '); } *nam1end = '\0'; un_quote_string(nam1); un_quote_string(nam1end+4); if(symlink(nam1,nam1end+4) && (unlink(nam1end+4) || symlink(nam1,nam1end+4))) msg_perror("Can't symlink %s to %s",nam1,nam1end+4); else if(f_verbose) msg("Symlinkd %s to %s",nam1,nam1end+4); } #endif else msg("Unknown demangling command %s",ptr); } }