From: dbl@osf.ORG
Subject: utils/progs: minor diffs to lndir.c to preserve links
Organization: The Internet
Date: Thu, 30 Jul 1992 12:54:04 GMT



VERSION:
    R5, public-patch-13

CLIENT MACHINE and OPERATING SYSTEM:
    Sparc/SunOS 4.1.1

DISPLAY TYPE:

WINDOW MANAGER:

COMPILER:

AREA:
	util/progs

SYNOPSIS:
	In some cases it is useful to have lndir preserve values of links.

DESCRIPTION:

Normally for a directory such as this:

craft% ls -lR ../src
total 8
-rw-r--r--  1 david           8 Jul 29 22:12 A
lrwxrwxrwx  1 david           1 Jul 29 22:13 B -> A
lrwxrwxrwx  1 david          12 Jul 29 22:10 C -> /tmp/junkdir
lrwxrwxrwx  1 david           8 Jul 29 22:14 D -> /tmp/non
lrwxrwxrwx  1 david           1 Jul 29 22:17 E -> .
lrwxrwxrwx  1 david          12 Jul 29 22:17 F -> /usr/bin/X11
drwxr-xr-x  2 david         512 Jul 29 22:16 subdir
drwxr-xr-x  2 david         512 Jul 29 22:16 subdir2

./src/subdir:
total 2
lrwxrwxrwx  1 david           7 Jul 29 22:16 testB -> testing
-rw-r--r--  1 david           6 Jul 29 22:03 testing

./src/subdir2:
total 1
lrwxrwxrwx  1 david          17 Jul 29 22:16 testing -> ../subdir/testing


the lndir binary will produce 


craft% lndir ../src
craft% ls -lR 
total 8
lrwxrwxrwx  1 david           8 Jul 29 22:18 A -> ../src/A
lrwxrwxrwx  1 david           8 Jul 29 22:18 B -> ../src/B
lrwxrwxrwx  1 david           8 Jul 29 22:18 C -> ../src/C
lrwxrwxrwx  1 david           8 Jul 29 22:18 D -> ../src/D
lrwxrwxrwx  1 david           8 Jul 29 22:18 E -> ../src/E
lrwxrwxrwx  1 david           8 Jul 29 22:18 F -> ../src/F
drwxr-xr-x  2 david         512 Jul 29 22:18 subdir
drwxr-xr-x  2 david         512 Jul 29 22:18 subdir2

subdir:
total 2
lrwxrwxrwx  1 david          22 Jul 29 22:18 testB -> ../../src/subdir/testB
lrwxrwxrwx  1 david          24 Jul 29 22:18 testing -> ../../src/subdir/testing

subdir2:
total 1
lrwxrwxrwx  1 david          25 Jul 29 22:18 testing -> ../../src/subdir2/testing


but in many cases it is useful to preserve the structure of the link tree --
if file A changes in the local tree, for example, B is not correctly "updated"
but points back to the original tree.  It would be useful to have this happen:


craft% newlndir -preserve ../src
craft% ls -lR
total 8
lrwxrwxrwx  1 david           8 Jul 29 22:20 A -> ../src/A
lrwxrwxrwx  1 david           1 Jul 29 22:20 B -> A
lrwxrwxrwx  1 david          12 Jul 29 22:20 C -> /tmp/junkdir
lrwxrwxrwx  1 david           8 Jul 29 22:20 D -> /tmp/non
lrwxrwxrwx  1 david           1 Jul 29 22:20 E -> .
lrwxrwxrwx  1 david          12 Jul 29 22:20 F -> /usr/bin/X11
drwxr-xr-x  2 david         512 Jul 29 22:20 subdir
drwxr-xr-x  2 david         512 Jul 29 22:20 subdir2

subdir:
total 2
lrwxrwxrwx  1 david           7 Jul 29 22:20 testB -> testing
lrwxrwxrwx  1 david          24 Jul 29 22:20 testing -> ../../src/subdir/testing

subdir2:
total 1
lrwxrwxrwx  1 david          17 Jul 29 22:20 testing -> ../subdir/testing


where files which are links in the original tree preserve their relative 
structure.

REPEAT BY:

Here's the set of diffs I'm using:
	- one of my goals was changing as little as possible; there is 
		probably a way to do this optimizing calls to readlink
	- hasn't been tested exhaustively; caveat emptor

David B. Lewis  	Yet another new address!: david%craft@uunet.uu.net 
"This is a war of engines and octanes. I drink to the American auto industry 
and the American oil industry." -- Joseph Stalin, sometime during WWII.


SAMPLE FIX:

apply to mit/util/progs/lndir.c:

*** lndir.c	Mon Jul 22 14:48:57 1991
--- newlndir.c	Wed Jul 29 21:22:43 1992
***************
*** 55,60 ****
--- 55,61 ----
  
  extern int errno;
  int silent;
+ int preserveLinks;
  
  void
  quit (code, fmt, a1, a2, a3)
***************
*** 162,167 ****
--- 163,181 ----
  	}
  
  	/* non-directory */
+ 	if (preserveLinks)
+ 	{
+ 	int srclen;
+ 	/* if the original file is a link, preserve the value */
+ 	srclen = readlink(buf, symbuf, sizeof(symbuf) -1);
+ 	if ((-1 != srclen) && (srclen > 0))
+ 		{
+ 		symbuf[srclen] = '\0';
+ 		if (symlink (symbuf, dp->d_name) == 0) 
+ 			continue;
+ 		/* else fall through and handle normally */
+ 		}
+ 	}
  	if (symlink (buf, dp->d_name) < 0) {
  	    int saverrno = errno;
  	    int symlen;
***************
*** 183,202 ****
  int ac;
  char **av;
  {
!     char *fn, *tn;
      struct stat fs, ts;
  
      silent = 0;
!     if (ac > 1 && !strcmp(av[1], "-silent")) {
  	silent = 1;
!     }
!     if (ac < silent + 2 || ac > silent + 3)
! 	quit (1, "usage: %s [-silent] fromdir [todir]", av[0]);
! 
!     fn = av[silent + 1];
!     if (ac == silent + 3)
! 	tn = av[silent + 2];
      else
  	tn = ".";
  
      /* to directory */
--- 197,231 ----
  int ac;
  char **av;
  {
!     char *fn = NULL, *tn = NULL;
      struct stat fs, ts;
+     int item;
  
+ #define USAGE "usage: %s [-silent] [-preserve] fromdir [todir]"
      silent = 0;
!     preserveLinks = 0;
!     for (item = 1; item < ac; item++)
! 	{
! 	if (!strcmp(av[item], "-silent")) 
  		silent = 1;
! 	else if (!strcmp(av[item], "-preserve")) 
! 		preserveLinks = 1;
  	else 
+ 		{
+ 		if (NULL == fn)
+ 			fn = av[item];
+ 		else
+ 			{
+ 			if (NULL == tn)
+ 				tn = av[item];
+ 			else
+ 				quit (1, USAGE, av[0]); 
+ 			}
+ 		}
+ 	}
+     if (NULL == fn)
+ 	quit (1, USAGE, av[0]); 
+     if (NULL == tn)
  	tn = ".";
  
      /* to directory */

Newsgroups: comp.windows.x