From: "Juan Manuel Guerrero" Organization: Darmstadt University of Technology To: djgpp AT delorie DOT com Date: Wed, 10 Nov 1999 23:20:31 +0100 Subject: Re: djlsr203 (990819) X-mailer: Pegasus Mail for Windows (v2.54DE) Message-ID: <64E74171C6@HRZ1.hrz.tu-darmstadt.de> Reply-To: djgpp AT delorie DOT com On Tue, 26 Oct 1999, Eli Zaretskii wrote: >On Tue, 12 Oct 1999, Juan Manuel Guerrero, Student, FB05 wrote: > >> When decompressing a tgz-file with an entry of the form: >> libg++-1.2.3/libg++/readme.g++ >> the program performs the substitution: >> ++ --> plus. >> It should be clear that this substitution must be applied to all >> occuriences of "++" and not only to the first as the program does. > >Thanks for the report and the patches. > >I corrected the problem in DJTAR a bit differently; see the patch below. >The corrected version will be in DJGPP v2.03. First: sorry for delay but i was busy. I have applied your patch and i think it is worth to note that there is still an error in function: get_new_name. I will make reference to the original code from djlsr203 (990819). If you inspect the code concerning the tests and substitutions you will see that it looks like this: if (info) { code for substitution: .info-NNN -> .iNNN } else { code for testing all the other things and executing the corresponding substitutions. } This is an error. Example: libg++-1.2.3/libg++.info-123 The string ".info-" will be found but the string "++" will never be found. At least in this case the tests make no sense. Even worse, if you inspect the code following the else statement you will see that the same way of testing is applied: if (tgz) { code for substitution: .tar.gz -> .tgz } else { code for testing "++" occuriences and executing the corresponding substitutions, etc. } This will fail again at least with this example: libg++-1.2.3/foo.tar.gz The occurience of "tar.gz" will be detected but NOT the occurience of "++". The error is makeing the execution of the next test depending on the result of the last test. In my opinion ALL or ALMOST ALL tests MUST be applied in a sequential way. What i mean is: if (info) { code for substitution: .info-NNN -> .iNNN } if (tgz) { code for substitution: .tar.gz -> .tgz } if (plus) { code for substitution: ++ -> xx } etc, etc, etc. For my private use of DJTAR I have defined the following tests and tests sequences. (Private use means that my code works, but the quality of it is poor and was never intented for submission.) 1) MULTIPLE DOT test. This code tests for occuriences of multiple dots in the directory part of the path. Example: ./../foo-1.2.3/bar-4.5/ -> ./../foo-1.2-3/bar-4.5/ .\..\foo-1.2.3\bar-4.5\ -> .\..\foo-1.2-3\bar-4.5\ 1. File names will NOT been modified by this test and are treated later. 2. If there are mixed slashs and backslashs the code will fail. 2) NOT ALLOWED CHARS test. This code will delete from the whole tar entry (dir part and file name part) all spaces and tabs. It will also replace chars that are not allowed on MSDOS, especially + -> x = -> # It tests for ALL not allowed chars under MSDOS and performs an arbitrary substitution (see patch). Special testing for "++" is now superfluous. 3) TAR.ANY_COMPRESSOR_EXTENSION test. Any compressor extension means: .z, .Z, .gz, .bz, .bz2, .bzip2, .Y This implies the following substitutions: foo.tar.(z,Z) --> foo.taz foo.tar.gz --> foo.tgz foo.tar.(bz,bz2,bzip2) --> foo.tbz foo.tar.Y --> foo.tay Because the extension is important, one more substitution is performed: foo-1.2.3.4.(taz,tgz,tbz,tay) --> foo-1234.(taz,tgz,tbz,tay) If this substitution is not applied, the original DJTAR multiple dot test will perform the following substitution: foo-1.2.3.4.tar.gz --> foo-1.2-3-4-tgz --> foo-1.2-3 The last substitution (truncation) is done by DOS and the average user will never notice that the file is an archive. 4) INFO test. 4.1) Test for compressed info files. Texinfo-3.12 supports the following decompressors: uncompress, gunzip, bunzip2 and unyabba. For the DJGPP port of Texinfo-3.12 the following applies: foo --> foo.gz foo.inf --> foo.igz or foo.inz foo.iN --> foo.iNz foo.iNN --> foo.NNz foo.NNN --> foo-NNN.z This implies the following substitutions: foo.info.(z,Z,gz,bz,bz2,bzip2,Y) --> foo.in(z,b,y) foo.info-N.(z,Z,gz,bz,bz2,bzip2,Y) --> foo.iN(z,b,y) foo.info-NN.(z,Z,gz,bz,bz2,bzip2,Y) --> foo.NN(z,b,y) foo.info-NNN.(z,Z,gz,bz,bz2,bzip2,Y) --> foo-NNN.(z,bz2,y) (z,Z,gz,bz,bz2,bzip2,Y) means: one of the possible compressor extensions. N means: one info digit. I know that there is no MSDOS/DJGPP port for some of the compressors but the files must be extracted correctely from the tar-archive. 4.2) Test for NOT compressed info files. For the DJGPP port of Texinfo-3.12 the following substitutions applies: foo.info --> foo.inf foo.info-N --> foo.inN foo.info-NN --> foo.iNN foo.info-NNN --> foo.NNN foo.info-NNNN --> foo-NNNN 5) SPECIAL FILES test. The definition of a special file is COMPLETELY ARBITRARY and represents only my opinion. Renaming of special files: .foo --> _foo .lex. --> _lex. .tab. --> _tab. config.h.in --> config_h.in config.h.bot --> config_h.bot config.h.top --> config_h.top Makefile.am.in --> Mkfileam.in Makefile.in.in --> Mkfilein.in intlh.inst.in --> intlhinst.in po2tbl.sed.in --> po2tblsed.in texinfo.texi --> texinfo.txi ChangeLog- --> CLog ChangeLog. --> CLog All other files that can not be extracted without violating the 8.3 file name restriction (means: multiple dots, ignoring difference between upper and lower case names, etc, etc, etc) will fail to be extracted. This is COMPLETELY INTENSIONAL. The user shall notice that something is wrong. The original DJTAR will extract this file as: foo.1999Nov11.patch.gz --> foo.1999Nov11-patch-gz --> foo.199 The last truncation is done by DOS and in my opinion an average user will never notice that this is a gziped patch file for foo. I don't like this SILENT conversions of files. I prefer a warning and then skipping the file so I get a tarchange.lst file which I can use to make my own change list file. But this is only my private opinion. To make all this points clear: 1. The things concerning the if-else command sequence is in my opinion a bug and should be corrected. 2. The tests and tests sequence i have defined reflects only my private opinion and can be descarted by the maintainers of DJTAR. Although my code is probably of poor quality i send you a patch anyway. May be you can extract something usefull. The patch is based on the original DJLSR203 code. Regards, Guerrero, Juan Manuel. diff -aprNC3 djtar.alt/djtar.c djtar.neu/djtar.c *** djtar.alt/djtar.c Thu Jun 3 13:27:42 1999 --- djtar.neu/djtar.c Wed Nov 10 12:50:14 1999 *************** *** 2,7 **** --- 2,8 ---- /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + #include #include #include #include *************** guess_file_type(char *buf, register size *** 274,398 **** } /*------------------------------------------------------------------------*/ ! char new[2048]; /* got to think about LFN's! */ ! char * ! get_new_name(char *name_to_change, int *should_be_written) { ! char *changed_name, *info; ! /* ONLY_DIR says to extract only files which are siblings ! of that directory. */ ! *should_be_written = list_only == 0; ! if (*should_be_written && ! only_dir && strncmp(only_dir, name_to_change, strlen(only_dir))) ! *should_be_written = 0; ! changed_name = get_entry(name_to_change); ! if (*should_be_written && !to_stdout && NO_LFN(changed_name)) { ! info = strstr(changed_name, ".info-"); ! if (info) { ! strcpy(new, changed_name); ! info = strstr(new, ".info-"); ! strcpy(info+2, info+6); ! fprintf(log_out, "[ changing %s to %s ]\n", changed_name, new); } else { ! char *tgz = strstr(changed_name, ".tar.gz"); ! if (tgz) { ! strcpy(new, changed_name); ! tgz = strstr(new, ".tar.gz"); ! strcpy(tgz, ".tgz"); ! strcat(tgz, tgz+7); ! fprintf(log_out, "[ changing %s to %s ]\n", changed_name, new); } ! else { ! char *plus = strstr(changed_name, "++"), *plus2; ! if (plus) ! { ! strcpy(new, changed_name); ! plus2 = strstr(new, "++"); ! strcpy(plus2, "plus"); ! strcpy(plus2+4, plus+2); ! fprintf(log_out, "[ changing %s to %s ]\n", changed_name, new); ! } ! else ! { ! strcpy(new, changed_name); ! } } } ! changed_name = new; ! if (dot_switch) { ! char *p = changed_name, *name_start = changed_name; ! int state = 0; ! /* 0 = start of item ! 1 = before dot (not counting initial dot), but not first char ! 2 = after first dot */ ! ! /* ".gdbinit" -> "_gdbinit" ! "emacs-19.28.90/ChangeLog" -> "emacs-19.28-90/ChangeLog" ! "./dir/file" -> "./dir/file" ! "sh.lex.c" -> "sh_lex.c" ! */ ! while (*p) { ! switch (*p++) ! { ! case '/': ! case '\\': ! state = 0; ! name_start = p; ! break; ! case '.': ! /* Don't waste our limited 8-char real estate in the ! name part too early, unless the name is really short. */ ! if (state == 1 && p - name_start < 5) ! { ! size_t namelen = strlen(p); ! char *next_slash = memchr(p, '/', namelen); ! char *next_bslash = memchr(p, '\\', namelen); ! char *next_dot = memchr(p, '.', namelen); ! ! /* Find where this name ends. */ ! if (next_slash == (char *)0) ! { ! if (next_bslash) ! next_slash = next_bslash; ! else ! next_slash = p + namelen; ! } ! ! else if (next_bslash && next_bslash < next_slash) ! next_slash = next_bslash; ! ! /* If name has more dots, convert this one to `_'. */ ! if (next_dot && next_dot < next_slash) ! { ! p[-1] = '_'; ! break; /* don't bump `state' */ ! } ! } ! ! /* Leave "./", "../", "/." etc. alone. */ ! if (state != 0 || ! (*p && *p != '/' && *p != '\\' && *p != '.')) ! p[-1] = "_.-"[state]; ! if (state < 2) state++; ! break; ! default: ! if (state == 0) state = 1; ! } } } } return changed_name; } --- 275,728 ---- } /*------------------------------------------------------------------------*/ ! void ! replace_multiple_dots_in_path(char *changed_name) ! { ! char dir_separator = '/'; ! if (strchr(changed_name, '\\')) ! dir_separator = '\\'; ! ! if (dir_separator) ! { ! char *dir, *dot, *slash, temp; ! ! dir = changed_name; ! while ((slash = strchr(dir, dir_separator))) ! { ! temp = *++slash; /* remember char after slash. */ ! *slash = '\0'; ! dot = strchr(dir, '.'); ! if (dot && *(dot + 1) != '.') ! while ((dot = strchr(++dot, '.'))) /* Don't modify: "./", "../", "/.". */ ! *dot = '-'; ! *slash = temp; /* restore char. */ ! dir = slash; /* next directory. */ ! } ! } ! } ! ! /*------------------------------------------------------------------------*/ ! /****************************************************************** ! * Substitutions for not allowed characters in archive entries. * ! * 1.: Delete white space and tabs. * ! * 2.: Subtitute chars that are not allowed under MSDOS. * ! ******************************************************************/ ! ! void ! replace_illegal_chars(char *changed_name) { ! static struct { ! const char orig_char, new_char; ! } illegal_chars[] = { ! { '+', 'x' }, ! { '=', '#' }, ! { ',', '`' }, ! { ';', '\'' }, ! { ':', '@' }, ! { '\"', '^' }, ! { '[', '{' }, ! { ']', '}' }, ! { '<', '(' }, ! { '>', ')' }, ! { '|', '!' }, ! { '\\', '$' }, ! { '?', '%' }, ! { '*', '&' } ! }; ! static int index_max = sizeof illegal_chars / sizeof illegal_chars[0]; ! int index; ! char *illegal_char; ! ! illegal_char = changed_name; ! while ((illegal_char = strchr(illegal_char, ' '))) ! strcpy(illegal_char, illegal_char + 1); /* delete space and tab. */ ! for (index = 0; index < index_max; index++) ! { ! illegal_char = changed_name; ! while ((illegal_char = strchr(illegal_char, illegal_chars[index].orig_char))) ! *illegal_char = illegal_chars[index].new_char; ! } ! } ! /*------------------------------------------------------------------------*/ ! /**************************************************** ! * Substitutions for known archive extensions. * ! * filename.tar.z --> filename.taz * ! * filename.tar.Z --> filename.taz * ! * filename.tar.gz --> filename.tgz * ! * filename.tar.bzip2 --> filename.tbz * ! * filename.tar.bz2 --> filename.tbz * ! * filename.tar.bz --> filename.tbz * ! * filename.tar.Y --> filename.tay * ! * * ! * An archive extension must always be preserved. * ! * filename-1.2.3.4.taz --> filename-1234.taz * ! * filename-1.2.3.4.tgz --> filename-1234.tgz * ! * filename-1.2.3.4.tbz --> filename-1234.tbz * ! * filename-1.2.3.4.tay --> filename-1234.tay * ! ****************************************************/ ! ! void ! replace_archive_extensions(char *changed_name) ! { ! static struct { ! const char *orig_ext, *new_ext; ! const int orig_ext_len; ! } tar_zext[] = { ! { ".tar.z", ".taz", 6 }, ! { ".tar.Z", ".taz", 6 }, ! { ".tar.gz", ".tgz", 7 }, ! { ".tar.bzip2", ".tbz", 11 }, ! { ".tar.bz2", ".tbz", 9 }, ! { ".tar.bz", ".tbz", 7 }, ! { ".tar.Y", ".tay", 6 } ! }; ! static int index_max = sizeof tar_zext / sizeof tar_zext[0]; ! int index; ! char *filename = basename(changed_name); ! ! for (index = 0; index < index_max; index++) { ! char *tar_any_zext = strstr(filename, tar_zext[index].orig_ext); ! if (tar_any_zext) { ! ! char *dot; ! tar_any_zext = strstr(filename, tar_zext[index].orig_ext); ! strcpy(tar_any_zext, tar_zext[index].new_ext); ! strcat(tar_any_zext, tar_any_zext + tar_zext[index].orig_ext_len); ! ! dot = strchr(filename, '.'); ! while ((dot = strchr(dot, '.')) != tar_any_zext--) ! strcpy(dot, dot + 1); } + } + } + + /*------------------------------------------------------------------------*/ + /********************************************************************** + * Substitutions for info files. * + * 1.: uncompressed info file: * + * foo.info --> foo.inf * + * foo.info-N --> foo.inN * + * foo.info-NN --> foo.iNN * + * foo.info-NNN --> foo.NNN * + * foo.info-NNNNN --> fo-NNNNN * + * 2.: compressed info file: * + * foo.info.(z,Z,gz,bz,bz2,bzip2,Y) --> foo.in(z,b,y) * + * foo.info-N.(z,Z,gz,bz,bz2,bzip2,Y) --> foo.iN(z,b,y) * + * foo.info-NN.(z,Z,gz,bz,bz2,bzip2,Y) --> foo.NN(z,b,y) * + * foo.info-NNN.(z,Z,gz,bz,bz2,bzip2,Y) --> foo-NNN.(z,b,y) * + * foo.info-NNNNN.(z,Z,gz,bz,bz2,bzip2,Y) --> fo-NNNNN.(z,b,y) * + * with: * + * z,Z,gz,bz,bz2,bzip2,Y: known compressor extensions. * + **********************************************************************/ + + #define OFFSET 6 /* OFFSET is the length of string ".info-". */ + #define EIGHT_CHARS 8 /* max characters of valid dos file name. */ + #define SEVEN_CHARS 7 + + int + replace_info_extension(char *changed_name) + { + + static struct { + const char *orig_ext; + const int orig_ext_len; + } any_z_ext[] = { + { ".z", 2 }, + { ".Z", 2 }, + { ".gz", 3 }, + { ".bzip2", 6 }, + { ".bz2", 4 }, + { ".bz", 3 }, + { ".Y", 2 } + }; + + static int index_max = sizeof any_z_ext / sizeof any_z_ext[0]; + char *filename = basename(changed_name); + char *info_ext = strstr(filename, ".info-"); + + /* longfoo.info-bar --> long-inf.bar */ + if (info_ext && isalpha(*(info_ext + OFFSET))) + { + if (info_ext - filename > 4) + strcpy(filename + 4, info_ext); + info_ext = strstr(filename, ".info-"); + *info_ext = '_'; /* . --> _ */ + *(info_ext + OFFSET - 1) = '.'; /* - --> . */ + return 0; + } + + /* info extension with an numerical index. */ + if (info_ext) + { + int info_digits; + char *dot = strchr(info_ext + OFFSET, '.'); /* first dot beyond ".info-" */ + if (dot) /* number of digits in .info-NNNNNNN */ + info_digits = (int) (dot - (info_ext + OFFSET)); else + info_digits = strlen(info_ext + OFFSET); + + if (info_digits > 6) + /* info digits to large for file name space (8 chars). + At least place for 2 chars in file name must remain. + File name must looks like: x-NNNNNN or x-NNNNNN.(z,Z,gz,bz,bz2,bzip2,Y) + z,Z,gz,bz,bz2,bzip2,Y: possible compressor extensions. + */ + return 1; /* let the user decide. */ + else if (info_digits > 3) { ! char *any_zext; ! int filename_len = (int) (info_ext - filename); ! if (SEVEN_CHARS - (filename_len + info_digits) >= 0) ! /* File name plus info digits fits in 8 chars. ! Info digits will be appended to file name. ! foo.info-NNNN --> foo-NNNN or ! foo.info-NNNN.(z,Z,gz,bz,bz2,bzip2,Y) --> foo-NNNN.(z,Z,gz,bz,bz2,bzip2,Y) ! */ ! strcpy (filename + filename_len, info_ext + OFFSET - 1); ! else { ! /* File name has 8 or more chars or ! file name plus info digits are more than 8 chars long. ! File name will be truncated accordingly. ! longfilename.info-NNNN --> lon-NNNN or ! longfilename.info-NNNN.(z,Z,gz,bz,bz2,bzip2,Y) --> lon-NNNN.(z,Z,gz,bz,bz2,bzip2,Y) ! foo.info-NNNNN --> fo-NNNNN or ! foo.info-NNNNN.(z,Z,gz,bz,bz2,bzip2,Y) --> fo-NNNNN.(z,Z,gz,bz,bz2,bzip2,Y) ! */ ! strcpy (filename + SEVEN_CHARS - info_digits, info_ext + OFFSET - 1); } ! if ((any_zext = strstr(filename, ".bzip2"))) ! strcpy(any_zext + 3, any_zext + 5); /* .bzip2 --> .bz2. */ ! } ! else if (info_digits == 3) ! { ! if (dot) /* info file has probably an compressor extension. */ ! { ! char *any_zext; ! int filename_len = (int) (info_ext - filename); ! if (SEVEN_CHARS - (filename_len + info_digits) >= 0) ! /* File name plus info digits fits in 8 chars. ! Info digits will be appended to file name. ! foo.info-NNN.(z,Z,gz,bz,bz2,bzip2,Y) --> foo-NNN.(z,Z,gz,bz,bz2,bzip2,Y) ! */ ! strcpy (filename + filename_len, info_ext + OFFSET - 1); ! else ! { ! /* File name has 8 or more chars or ! file name plus info digits are more than 8 chars long. ! File name will be truncated accordingly. ! longfilename.info-NNN.(z,Z,gz,bz,bz2,bzip2,Y) --> long-NNN.(z,Z,gz,bz,bz2,bzip2,Y) ! foobar.info-NNN.(z,Z,gz,bz,bz2,bzip2,Y) --> foob-NNN.(z,Z,gz,bz,bz2,bzip2,Y) ! */ ! strcpy (filename + SEVEN_CHARS - info_digits, info_ext + OFFSET - 1); ! } ! if ((any_zext = strstr(filename, ".bzip2"))) ! strcpy(any_zext + 3, any_zext + 5); /* .bzip2 --> .bz2. */ ! } ! else /* uncompressed info file. */ ! /* filename.info-NNN --> filename.NNN */ ! strcpy(info_ext + 1, info_ext + OFFSET); ! } ! else if (info_digits <= 2) ! { ! int index; ! ! switch (info_digits) /* Delete ".info-" string. */ ! { ! case 2: /* foo.info-NN.(z,Z,gz,bz,bz2,bzip2,Y) --> foo.iNN.(z,Z,gz,bz,bz2,bzip2,Y) */ ! strcpy(info_ext + 2, info_ext + OFFSET); ! break; ! case 1: /* foo.info-N.(z,Z,gz,bz,bz2,bzip2,Y) --> foo.inN.(z,Z,gz,bz,bz2,bzip2,Y) */ ! strcpy(info_ext + 3, info_ext + OFFSET); ! break; ! } ! ! for (index = 0; index < index_max; index++) { ! char *any_zext = strstr(info_ext, any_z_ext[index].orig_ext); ! if (any_zext) /* info file has an compressor extension. */ ! { ! /* Info digits fits in extension. */ ! switch (*(any_zext + 1)) ! { ! case 'z': case 'Z': ! /******************************** ! * foo.iNN.(z,Z) --> foo.iNNz * ! * foo.inN.(z,Z) --> foo.inNz * ! ********************************/ ! strcpy(any_zext, any_zext + 1); ! break; ! case 'g': ! /***************************** ! * foo.iNN.gz --> foo.iNNz * ! * foo.inN.gz --> foo.inNz * ! *****************************/ ! strcpy(any_zext, any_zext + 2); ! break; ! case 'b': ! /***************************************** ! * foo.iNN.(bz,bz2,bzip2) --> foo.iNNb * ! * foo.inN.(bz,bz2,bzip2) --> foo.inNb * ! *****************************************/ ! strcpy(any_zext, any_zext + 1); ! strcpy(any_zext + 1, any_zext + any_z_ext[index].orig_ext_len - 1); ! break; ! case 'Y': ! /**************************** ! * foo.iNN.Y --> foo.iNNy * ! * foo.inN.Y --> foo.inNy * ! ****************************/ ! strcpy(any_zext, any_zext + 1); ! break; ! } ! ! switch (info_digits) ! { ! case 2: /* foo.iNN(z,b,y) --> foo.NN(z,b,y) */ ! strcpy(info_ext + 1, info_ext + 2); ! break; ! case 1: /* foo.inN(z,b,y) --> foo.iN(z,b,y) */ ! strcpy(info_ext + 2, info_ext + 3); ! break; ! } ! break; ! } } } ! } ! info_ext = strstr(filename, ".info."); ! if (info_ext) ! { ! int index; ! for (index = 0; index < index_max; index++) { ! char *any_zext = strstr(info_ext, any_z_ext[index].orig_ext); ! if (any_zext) { ! /* filename.info.(z,Z,gz,bz,bz2,Y) -> filename.in(z,b,y) */ ! switch (*(any_zext + 1)) ! { ! case 'z': case 'Z': /* foo.info.(z,Z) --> foo.inz */ ! strcpy(info_ext + 3, any_zext + 1); ! break; ! case 'g': /* foo.info.gz --> foo.inz */ ! strcpy(info_ext + 3, any_zext + 2); ! break; ! case 'b': /* foo.info.(bz,bz2,bzip2) --> foo.inb */ ! strcpy(info_ext + 3, any_zext + 1); ! strcpy(info_ext + 4, any_zext + any_z_ext[index].orig_ext_len - 3); ! break; ! case 'Y': /* foo.info.Y --> foo.iny */ ! strcpy(any_zext, any_zext + 1); ! break; ! } } } } + return 0; + } + + /*------------------------------------------------------------------------*/ + + void + rename_special_files(char *changed_name) + { + static struct { + const char *orig_name, *new_name; + const int orig_name_len; + + } file_names[] = { + { "Makefile.am.in", "Mkfileam.in", 14 }, + { "Makefile.in.in", "Mkfilein.in", 14 }, + { "intlh.inst.in", "intlhinst.in", 13 }, + { "po2tbl.sed.in", "po2tblsed.in", 13 }, + { "texinfo.texi", "texinfo.txi", 12 }, + { "ChangeLog-", "CLog", 10 }, + { "ChangeLog.", "CLog", 10 } + }; + static int index_max = sizeof file_names / sizeof file_names[0]; + int index; + char *dot, *rest_of_line, *filename = basename(changed_name); + + /************************************* + * .foo --> _foo * + * .lex. --> _lex. * + * .tab. --> _tab. * + * config.h.in --> config_h.in * + * config.h.bot --> config_h.bot * + * config.h.top --> config_h.top * + *************************************/ + + if (*filename == '.') + *filename ='_'; + if ((dot = strstr(filename, ".lex."))) + *dot = '_'; + if ((dot = strstr(filename, ".tab."))) + *dot = '_'; + if (strstr(filename, "config.h.")) + { + if ((dot = strstr(filename, ".h.in"))) + *dot = '_'; + if ((dot = strstr(filename, ".h.bot"))) + *dot = '_'; + if ((dot = strstr(filename, ".h.top"))) + *dot = '_'; + } + + for (index = 0; index < index_max; index++) + { + rest_of_line = strstr(filename, file_names[index].orig_name) + + file_names[index].orig_name_len; + if (rest_of_line != (char *) file_names[index].orig_name_len) + { + strcpy(filename, file_names[index].new_name); + strcat(filename, rest_of_line); + break; + } + } + } + + /*------------------------------------------------------------------------*/ + char new [2048]; /* got to think about LFN's! */ + + char * + get_new_name(char *name_to_change, int *should_be_written) + { + char *changed_name; + + /* ONLY_DIR says to extract only files which are siblings + of that directory. */ + *should_be_written = list_only == 0; + if (*should_be_written && + only_dir && strncmp(only_dir, name_to_change, strlen(only_dir))) + *should_be_written = 0; + + changed_name = get_entry(name_to_change); + if (*should_be_written && !to_stdout && NO_LFN(changed_name)) + { + replace_multiple_dots_in_path(changed_name); + strcpy(new, changed_name); + replace_illegal_chars(changed_name); + if (*basename(changed_name) != NULL) + { + if (strstr(changed_name, ".tar.")) + replace_archive_extensions(changed_name); + if (strstr(changed_name, ".info")) + if (replace_info_extension(changed_name)) + goto leave; /* let the user decide. */ + if (strcmp (new, changed_name) != NULL) + fprintf(log_out, "[ changing %s to %s ]\n", new, changed_name); + if (dot_switch) + rename_special_files(changed_name); + } + } + leave: return changed_name; }