-/* mangle.c -- encode long filenames
- Copyright (C) 1988 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 <stdio.h>
-#include <sys/types.h>
-#include <time.h>
-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;
-
-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
+/* Encode long filenames for GNU tar.
+ Copyright 1988, 92, 94, 96, 97, 99, 2000 Free Software Foundation, Inc.
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <system.h>
+#include "common.h"
+#include <quotearg.h>
+
+struct mangled
+ {
+ struct mangled *next;
+ int type;
+ char mangled[NAME_FIELD_SIZE];
+ char *linked_to;
+ char normal[1];
+ };
+
+/* Extract a GNUTYPE_NAMES record contents. It seems that such are
+ not produced anymore by GNU tar, but we leave the reading code
+ around nevertheless, for salvaging old tapes. */
void
-add_symlink_mangle(symlink, linkto, buffer)
-char *symlink;
-char *linkto;
-char *buffer;
+extract_mangle (void)
{
- struct mangled *munge,*kludge;
+ off_t size = current_stat_info.stat.st_size;
+ char *buffer = xmalloc ((size_t) (size + 1));
+ char *copy = buffer;
+ char *cursor = buffer;
- 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
+ if (size != (size_t) size || size == (size_t) -1)
+ xalloc_die ();
-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);
-}
+ buffer[size] = '\0';
-void
-write_mangled()
-{
- struct mangled *munge;
- struct stat hstat;
- union record *header;
- char *ptr1,*ptr2;
- PTR the_buffer;
- int size;
- int bufsize;
+ while (size > 0)
+ {
+ union block *block = find_next_block ();
+ size_t available;
- 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);
+ if (!block)
+ {
+ ERROR ((0, 0, _("Unexpected EOF in mangled names")));
+ return;
}
-
- 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(bufsize<size) {
- bcopy(ptr1,header->charptr,bufsize);
- ptr1+=bufsize;
- size-=bufsize;
- userec(header+(bufsize-1)/RECORDSIZE);
- header=findrec();
- bufsize = endofrecs()->charptr - header->charptr;
+ available = available_space_after (block);
+ if (available > size)
+ available = size;
+ memcpy (copy, block->buffer, available);
+ copy += available;
+ size -= available;
+ set_next_block_after ((union block *) (block->buffer + available - 1));
+ }
+
+ while (*cursor)
+ {
+ char *next_cursor;
+ char *name;
+ char *name_end;
+
+ next_cursor = strchr (cursor, '\n');
+ *next_cursor++ = '\0';
+
+ if (!strncmp (cursor, "Rename ", 7))
+ {
+
+ name = cursor + 7;
+ name_end = strchr (name, ' ');
+ while (strncmp (name_end, " to ", 4))
+ {
+ name_end++;
+ name_end = strchr (name_end, ' ');
+ }
+ *name_end = '\0';
+ if (next_cursor[-2] == '/')
+ next_cursor[-2] = '\0';
+ unquote_string (name_end + 4);
+ if (rename (name, name_end + 4))
+ ERROR ((0, errno, _("%s: Cannot rename to %s"),
+ quotearg_colon (name), quote_n (1, name_end + 4)));
+ else if (verbose_option)
+ WARN ((0, 0, _("Renamed %s to %s"), name, name_end + 4));
}
- bcopy(ptr1,header->charptr,size);
- bzero(header->charptr+size,bufsize-size);
- userec(header+(size-1)/RECORDSIZE);
-}
-
-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));
+#ifdef HAVE_SYMLINK
+ else if (!strncmp (cursor, "Symlink ", 8))
+ {
+ name = cursor + 8;
+ name_end = strchr (name, ' ');
+ while (strncmp (name_end, " to ", 4))
+ {
+ name_end++;
+ name_end = strchr (name_end, ' ');
+ }
+ *name_end = '\0';
+ unquote_string (name);
+ unquote_string (name_end + 4);
+ if (symlink (name, name_end + 4)
+ && (unlink (name_end + 4) || symlink (name, name_end + 4)))
+ ERROR ((0, errno, _("%s: Cannot symlink to %s"),
+ quotearg_colon (name), quote_n (1, name_end + 4)));
+ else if (verbose_option)
+ WARN ((0, 0, _("Symlinked %s to %s"), name, name_end + 4));
}
- 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,' ');
- }
- 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);
- }
+ else
+ ERROR ((0, 0, _("Unknown demangling command %s"), cursor));
+
+ cursor = next_cursor;
+ }
}