[net.bugs.4bsd] bug in 4.2 version of tar

chris@pixutl.UUCP (Chris Bertin) (12/13/84)

There is a bug in tar (4.2) that makes it impossible to backup a first level
directory (say /usr, for example) unless you are in '/', as shown in the
following script.


Script started on Thu Dec 13 13:18:56 1984
@ pwd
/tmp
@ tar cvf /dev/null /usr
cannot change back?: /tmp//usr: No such file or directory
@ cd /
@ tar cvf /dev/null /usr
a /usr/src/cmd/Makefile 9 blocks
a ......
@ cd /lib
@ tar cvf /dev/null /usr
cannot change back?: /lib//usr: No such file or directory
@ 
script done on Thu Dec 13 13:20:21 1984


The problem was introduced when 'tar' was modified in order to handle
symbolic links. The following modifications will take care of it.

283c283,284
< 	register char *cp, *cp2;
---
> 	register char *cp;
> 	char *rindex();
311,312c312
< 		cp2 = *argv;
< 		if (!strcmp(cp2, "-C") && argv[1]) {
---
> 		if (!strcmp(*argv, "-C") && argv[1]) {
322,326c322,324
< 		for (cp = *argv; *cp; cp++)
< 			if (*cp == '/')
< 				cp2 = cp;
< 		if (cp2 != *argv) {
< 			*cp2 = '\0';
---
> 		if((cp = rindex(*argv, '/')) != NULL) {
> 			char keep = *(++cp);
> 			*cp = '\0';
330a329
> 			*cp = keep;
332,333d330
< 			*cp2 = '/';
< 			cp2++;
335c332,334
< 		putfile(*argv++, cp2, parent);
---
> 		else
> 			cp = *argv;
> 		putfile(*argv++, cp, parent);

for a clearer view of the problem, here is the old code:

	........
	(void) getcwd(wdir);
	while (*argv && ! term) {
		cp2 = *argv;
		if (!strcmp(cp2, "-C") && argv[1]) {
			argv++;
			if (chdir(*argv) < 0)
				perror(*argv);
			else
				(void) getcwd(wdir);
			argv++;
			continue;
		}
		parent = wdir; /* at this point, the parent is the current
				* directory
				*/
		for (cp = *argv; *cp; cp++)
			if (*cp == '/')
				cp2 = cp;
		/* if there is only one '/' in the argument and if that '/'
		 * is the first character, cp2 is still equal to *argv and
		 * therefore, the current directory will be passed to putfile
		 * as the parent instead of '/'.
		 */
		if (cp2 != *argv) {
			*cp2 = '\0';
			if (chdir(*argv) < 0) {
				perror(*argv);
				continue;
			}
			parent = getcwd(tempdir);
			*cp2 = '/';
			cp2++;
		}
		putfile(*argv++, cp2, parent);
		........

and now, the new code:

	........
	(void) getcwd(wdir);
	while (*argv && ! term) {
		if (!strcmp(*argv, "-C") && argv[1]) {
			argv++;
			if (chdir(*argv) < 0)
				perror(*argv);
			else
				(void) getcwd(wdir);
			argv++;
			continue;
		}
		parent = wdir;
		if((cp = rindex(*argv, '/')) != NULL) {
			char keep = *(++cp);
			*cp = '\0';
			if (chdir(*argv) < 0) {
				perror(*argv);
				continue;
			}
			*cp = keep;
			parent = getcwd(tempdir);
		}
		else
			cp = *argv;
		putfile(*argv++, cp, parent);
		........


---------------------------------------------------------------------------
Chris
-- 


 Chris Bertin            :         (617) 657-8720 x2318
 Pixel Computer Inc.     :
 260 Fordham Rd.         :  {allegra|ihnp4|cbosgd|ima|genrad|amd|harvard}\
 Wilmington, Ma 01887    :     !wjh12!pixel!pix