home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume37 / rslink / part01 < prev    next >
Encoding:
Text File  |  1993-05-24  |  27.1 KB  |  961 lines

  1. Newsgroups: comp.sources.misc
  2. From: wilson@wakeman.europarc.xerox.com (Tim Wilson)
  3. Subject: v37i085:  rslink - recursive symbolic link, shadow directory trees, Part01/01
  4. Message-ID: <1993May25.192243.29358@sparky.imd.sterling.com>
  5. Summary: Copy directory hierarchy populating with symbolic links to originals
  6. X-Md4-Signature: e0535ba251101100d14bd634e96f4910
  7. Keywords: links, symbolic links, copying, shadow directory trees, directory hierarchy
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Reply-To: Tim Wilson <wilson@europarc.xerox.com>
  10. Organization: Rank Xerox Cambridge EuroPARC, UK
  11. Date: Tue, 25 May 1993 19:22:43 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13.  
  14. Submitted-by: wilson@wakeman.europarc.xerox.com (Tim Wilson)
  15. Posting-number: Volume 37, Issue 85
  16. Archive-name: rslink/part01
  17. Environment: UNIX, Perl, symlink
  18.  
  19. NAME
  20.      rslink - Recursive symbolic link (relative or absolute)
  21.  
  22. SYNOPSIS
  23.      rslink [-a] [-q] [-r] [-s] [-u] [-v] fromdir todir [ ignore ... ]
  24.  
  25. DESCRIPTION
  26.      Rslink creates a shadow directory tree:  a  replica  of  the
  27.      source  directory  tree  structure,  populated with symbolic
  28.      links to the original non-directory files.
  29.  
  30.      Shadow trees are useful, for example,
  31.  
  32.      o    for compiling a source tree for  several  architectures
  33.           (each has its own shadow tree of the sources), and
  34.  
  35.      o    in shared development by several programmers from a set
  36.           of  master  sources:  each developer makes local copies
  37.           only of files he wishes to modify.
  38.  
  39.      Relative symbolic links are useful because  they  are  still
  40.      valid if the tree rooted at the common ancestor is moved.
  41.  
  42.      Why use rslink?  Rslink is much faster  than  similar  shell
  43.      scripts.  How much faster depends on the speed of your discs
  44.      and  file  servers.    It  is  very  nearly  as  fast  as an 
  45.      equivalent C program I wrote just to compare performance!
  46.  
  47. I hope you find this as useful as we have!
  48.  
  49. Tim Wilson
  50. - Cut here -----------------------------------------------------------
  51. #! /bin/sh
  52. # This is a shell archive.  Remove anything before this line, then unpack
  53. # it by saving it into a file and typing "sh file".  To overwrite existing
  54. # files, type "sh file -c".  You can also feed this as standard input via
  55. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  56. # will see the following message at the end:
  57. #        "End of archive 1 (of 1)."
  58. # Contents:  ChangeLog MANIFEST Makefile README rslink rslink.1
  59. # Wrapped by wilson@wakeman on Fri May 21 10:29:57 1993
  60. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  61. if test -f ChangeLog -a "${1}" != "-c" ; then 
  62.   echo shar: Will not over-write existing file \"ChangeLog\"
  63. else
  64. echo shar: Extracting \"ChangeLog\" \(882 characters\)
  65. sed "s/^X//" >ChangeLog <<'END_OF_ChangeLog'
  66. XFri May 21 10:02:43 1993  Tim Wilson  (wilson@europarc.xerox.com)
  67. X
  68. X    * Version 1.20 released.  Submitted to comp.sources.misc.
  69. X
  70. XMon May 10 15:18:09 1993  Tim Wilson (wilson@europarc.xerox.com)
  71. X
  72. X    * Incompatible change: symbolic links to directories are now
  73. X    treated like symbolic links rather than like directories.  This is
  74. X    useful, whereas the original behaviour was never useful.  Clarify
  75. X    man page.
  76. X
  77. XThu Apr  9 14:28:17 1992  Tim Wilson  (tdw@cl.cam.ac.uk)
  78. X
  79. X    * David Kaelbling (drk@rational.com) suggests special treatment
  80. X    for symbolic links.  Add -r and -s options, which cause rslink to
  81. X    copy the _contents_ of relative and absolute symbolic links
  82. X    respectively. 
  83. X
  84. X    Add -u option -- update target tree, ignoring files that exist
  85. X    already.
  86. X
  87. X    Add -q (quiet) option.
  88. X
  89. X
  90. XWed Mar 11 11:50:41 1992  Tim Wilson  (tdw at cl.cam.ac.uk)
  91. X
  92. X    * Version 1.00 released.  Posted to alt.sources.
  93. END_OF_ChangeLog
  94. if test 882 -ne `wc -c <ChangeLog`; then
  95.     echo shar: \"ChangeLog\" unpacked with wrong size!
  96. fi
  97. # end of overwriting check
  98. fi
  99. if test -f MANIFEST -a "${1}" != "-c" ; then 
  100.   echo shar: Will not over-write existing file \"MANIFEST\"
  101. else
  102. echo shar: Extracting \"MANIFEST\" \(430 characters\)
  103. sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
  104. X   File Name        Archive #    Description
  105. X-----------------------------------------------------------
  106. X ChangeLog                 1    History file
  107. X MANIFEST                  1    This shipping list
  108. X Makefile                  1    Maintenance commands only
  109. X README                    1    Installation notes
  110. X rslink                    1    Perl script that creates shadow trees
  111. X rslink.1                  1    Man page for rslink (format with nroff -man)
  112. END_OF_MANIFEST
  113. if test 430 -ne `wc -c <MANIFEST`; then
  114.     echo shar: \"MANIFEST\" unpacked with wrong size!
  115. fi
  116. # end of overwriting check
  117. fi
  118. if test -f Makefile -a "${1}" != "-c" ; then 
  119.   echo shar: Will not over-write existing file \"Makefile\"
  120. else
  121. echo shar: Extracting \"Makefile\" \(321 characters\)
  122. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  123. X# Release 1.20.
  124. X# Last edited: Fri May 21 10:18:14 1993 by Tim Wilson
  125. X# $Id: Makefile,v 0.3 1993/05/21 09:27:54 wilson Exp $
  126. X
  127. X
  128. X           SRCS    = README Makefile rslink rslink.1
  129. X      SHARFILES    = $(SRCS)
  130. X
  131. Xall:
  132. X    @echo "Please select an explicit target"
  133. X
  134. Xshar: $(SHARFILES)
  135. X    makekit -m
  136. X
  137. Xclean:
  138. X    rm -f Part?? MANIFEST.BAK *~
  139. END_OF_Makefile
  140. if test 321 -ne `wc -c <Makefile`; then
  141.     echo shar: \"Makefile\" unpacked with wrong size!
  142. fi
  143. # end of overwriting check
  144. fi
  145. if test -f README -a "${1}" != "-c" ; then 
  146.   echo shar: Will not over-write existing file \"README\"
  147. else
  148. echo shar: Extracting \"README\" \(1718 characters\)
  149. sed "s/^X//" >README <<'END_OF_README'
  150. X$Id: README,v 0.2 1993/05/21 09:26:54 wilson Exp $
  151. X
  152. XWELCOME TO RSLINK RELEASE 1.20.
  153. X
  154. XThis is the second general posting of rslink. 
  155. X
  156. XPlease report bugs, enhancement, suggestions and comments to the
  157. Xauthor (address below).
  158. X
  159. XRslink is documented in the accompanying manual page in file rslink.1.
  160. X
  161. X
  162. XINSTALLATION
  163. X
  164. XTo install rslink:
  165. X
  166. X 1. Ensure that you have installed perl version 4.003 or higher.
  167. X
  168. X 2. If perl is installed somewhere other than /usr/local/bin/perl,
  169. X    edit the path name in the first line of "rslink" to point to your
  170. X    perl executable.
  171. X
  172. X 3. Copy the script "rslink" to the installation directory (eg
  173. X    /usr/local/bin) and make it executable (eg "chmod +x /usr/local/bin").
  174. X
  175. X 4. Copy the man page "rslink.1" to your man1 directory (eg
  176. X    /usr/local/man/man1). 
  177. X
  178. X
  179. XAVAILABILITY
  180. X
  181. XI can no longer offer rslink by FTP -- but it is probably available by
  182. XFTP from other sites.  Try a host that archives
  183. Xcomp.sources.misc.
  184. X
  185. X
  186. XCOPYRIGHT
  187. X
  188. XRslink is copyright (C) 1992, 1993 T D Wilson.  All rights reserved.
  189. XPermission to copy without fee all or part of this material is granted
  190. Xprovided that the copies are not made or distributed for direct
  191. Xcommercial advantage, the copyright notice and the title and date
  192. Xappear, and notice is given that copying is by permission of the
  193. Xauthor.  To copy otherwise, or to republish, requires specific
  194. Xpermission.  
  195. X
  196. X
  197. XNO WARRANTY
  198. X
  199. XT D Wilson makes no representations about the suitability
  200. Xof this software for any purpose.  It is provided "as is" without
  201. Xexpress or implied warranty.
  202. X
  203. X
  204. XAUTHOR
  205. X
  206. XInternet email address:
  207. X    wilson@europarc.xerox.com (until September 1993)
  208. X
  209. XPostal address:
  210. X    Tim Wilson
  211. X    c/o 43 Byron Avenue,
  212. X    Winchester
  213. X    Hants SO22 5AT
  214. X    England
  215. END_OF_README
  216. if test 1718 -ne `wc -c <README`; then
  217.     echo shar: \"README\" unpacked with wrong size!
  218. fi
  219. # end of overwriting check
  220. fi
  221. if test -f rslink -a "${1}" != "-c" ; then 
  222.   echo shar: Will not over-write existing file \"rslink\"
  223. else
  224. echo shar: Extracting \"rslink\" \(12446 characters\)
  225. sed "s/^X//" >rslink <<'END_OF_rslink'
  226. X#!/usr/local/bin/perl -w
  227. X#
  228. X# usage: rslink [-aqrsuv] fromdir todir [ignore ...]
  229. X#
  230. X# Performs recursive symbolic link .
  231. X# See man page for documentation.
  232. X#
  233. X# Release 1.20.
  234. X# Last edited: Fri May 21 10:17:23 1993 by Tim Wilson
  235. X# $Id: rslink,v 1.5 1993/05/21 09:17:31 wilson Exp $
  236. X#
  237. X# Modification summary
  238. X## Release 1.20.  Submitted to comp.sources.misc 21 May 1993.
  239. X#  10 May 1993    wilson    Incompatible change: symbolic links to directories
  240. X#            are now treated like symbolic links rather than
  241. X#            like directories.  This is useful, whereas the original
  242. X#            behaviour was never useful.
  243. X## Release 1.10.  Not posted.
  244. X#   9 Apr 1992    tdw    Add r (copy contents of relative symbolic
  245. X#            links), s (copy contents of absolute symbolic
  246. X#            links), u (update -- allow target to
  247. X#            exist), and q (quiet) options.
  248. X#            Idea for r and s from drk@COM.Rational (David
  249. X#            Kaelbling).
  250. X## Release 1.00.  Posted to alt.sources 11 March 1992.
  251. X#  20 Sep 1991    tdw    if -a and todir does not start with `/' (previously an
  252. X#            error), make relative via cwd.
  253. X#            Ignore list changed to be regexps.
  254. X#            Slight restructuring.
  255. X#  15 May 1991    tdw    Add -a (absolute) option
  256. X#   2 Nov 1990    tdw    Ignore `file exists' for directories too
  257. X#  25 Aug 1990    tdw    Ignore spurious `file exists' errors
  258. X#  17 Aug 1990    tdw    Created by Tim Wilson.
  259. X#
  260. X# Author: Tim Wilson, c/o 43 Byron Avenue, Winchester, Hants, SO22 5AT, UK.
  261. X#         wilson@europarc.xerox.com, tdw@cl.cam.ac.uk
  262. X#
  263. X######################################################################
  264. X#
  265. X# Symlink on NFS file systems is seen to give spurious `file exists'
  266. X# errors from time to time, which rslink just ignores, except for
  267. X# warning (suppressed by quiet mode).
  268. X#
  269. X# The errors are probably due to low-level retrys (because of network
  270. X# timeouts) of the non-idempotent NFS symlink operation.
  271. X#
  272. X######################################################################
  273. X#
  274. X# TO DO:
  275. X#  + Copy mode of created directories?  Not sure if this is a good idea.
  276. X#
  277. X######################################################################
  278. X#
  279. X# Copyright (C) 1992, 1993 T D Wilson.  All rights reserved.
  280. X#
  281. X# Permission to copy without fee all or part of this material is
  282. X# granted provided that the copies are not made or distributed for
  283. X# direct commercial advantage, the copyright notice and the title and
  284. X# date appear, and notice is given that copying is by permission of
  285. X# the author.  To copy otherwise, or to republish, requires specific
  286. X# permission.
  287. X#
  288. X# T D Wilson makes no representations about the suitability of this
  289. X# software for any purpose.  It is provided "as is" without express or
  290. X# implied warranty.
  291. X#
  292. X######################################################################
  293. X#
  294. X# Implementation contants
  295. X#
  296. X
  297. X$dirmode = 0755;        # Mode in which directories are created
  298. X
  299. X$EEXIST = 17;            # From Ultrix 3.1C errno.h
  300. X
  301. X
  302. X######################################################################
  303. X#
  304. X# Eliminate one-mention warnings
  305. X
  306. Xdefined $opt_a;
  307. X
  308. X######################################################################
  309. X#
  310. X# Parse options -- set $opt_a to 1 if -a present (etc)
  311. X#
  312. X
  313. X$0 =~ m|([^/]*)$|;        # progname is last component
  314. X$progname = $1;
  315. X
  316. X$options = "aqrsuv";
  317. X$usage = "usage: $progname [-$options] fromdir todir [ignore ...]";
  318. X
  319. X# Unset all option variables
  320. X
  321. X@flags = split (//, $options);
  322. Xforeach $letter (@flags) {
  323. X    eval "\$opt_$letter = 0";
  324. X}
  325. X
  326. X# Set from command line
  327. X
  328. X$usage_error = 0;
  329. XARG:
  330. Xwhile (@ARGV) {
  331. X    $arg = $ARGV[0];
  332. X    last ARG unless $arg =~ /^-/;
  333. X    shift @ARGV;
  334. X
  335. X    @flags = split (//, $arg);    # Get individual letters
  336. X    shift @flags;            # Drop leading -
  337. X    foreach $letter (@flags) {
  338. X        if (index ($options, $letter) >= $[) {
  339. X            eval "\$opt_$letter = 1";
  340. X        } else {
  341. X            warn "$progname: Unknown option -$letter\n";
  342. X            $usage_error++;
  343. X        }
  344. X    }
  345. X}
  346. Xdie "$usage\n" if ($usage_error || @ARGV < 2);
  347. X
  348. X($fromdir,$todir,@ignore) = @ARGV;
  349. X
  350. Xdefined($debug) || ($debug = 0);    # Boolean: don't actually make links
  351. X
  352. X
  353. X######################################################################
  354. X# 
  355. X# Subroutine to create a symbolic link
  356. X#
  357. X# arg 0: Contents of new symbolic link
  358. X# arg 1: Path name of new symbolic link that should not exist already
  359. X#
  360. X# Globals:
  361. X#   $debug
  362. X#   $opt_q -- quiet
  363. X#   $opt_v -- verbose
  364. X
  365. X
  366. Xsub dolink {
  367. X    local ($contents,$path) = @_;
  368. X
  369. X    $opt_v && print "ln -s $contents $path\n";
  370. X    unless ($debug || symlink($contents, $path)) {
  371. X        if ($! == $EEXIST) { # Assume NFS problem
  372. X            $opt_q || warn "$progname: symlink $path -> $contents:"
  373. X                . " $! -- IGNORING SPURIOUS ERROR\n";
  374. X        } else {    # Some other error
  375. X            die "$progname: Can't symlink "
  376. X                . "$path -> $contents: $!\n";
  377. X        }
  378. X    }
  379. X}
  380. X
  381. X
  382. X######################################################################
  383. X#
  384. X# Subroutine to test if file is required or should be omitted
  385. X#
  386. X# arg 0: file name -- just base name, not whole path
  387. X# arg 1: name of file for omitting message (see $opt_v below)
  388. X#
  389. X# Returns: True if file should be omitted
  390. X#
  391. X# Side effects: if $opt_v, prints message
  392. X#
  393. X# Global variables:
  394. X#  @ignore: the list of regexps matching files to be omitted
  395. X
  396. Xsub should_omit {
  397. X    local ($file,$name) = @_;
  398. X
  399. X    if (grep($file =~ /$_/, @ignore)) {
  400. X        if ($opt_v) { print "[Omitting $name]\n"; }
  401. X        return 1;
  402. X    }
  403. X    return 0;
  404. X}
  405. X
  406. X
  407. X######################################################################
  408. X# 
  409. X# Subroutine to recursively link a directory tree
  410. X#
  411. X# arg 0: path to destination directory from cwd;
  412. X#        which should not exist (unless $opt_u), with no trailing `/'
  413. X# arg 1: path from cwd to source directory, with no trailing `/'
  414. X# arg 2: depth: n "../"s are required to get back from the source to cd.
  415. X#        If depth is ABSOLUTE, the paths are assumed to be absolute.
  416. X#
  417. X# Create the destination directory.
  418. X#
  419. X# For each entry in the source directory (except . and .., and ignored files)
  420. X#   if it's a directory, recurse
  421. X#   else make a symbolic link
  422. X#
  423. X# Affected by the following global variables:
  424. X#   $debug
  425. X#   @ignore
  426. X#   $opt_q -- quiet
  427. X#   $opt_r -- copy contents of relative symbolic links
  428. X#   $opt_s -- copy contents of absolute symbolic links
  429. X#   $opt_u -- create files if they don't exist already
  430. X#   $opt_v -- verbose
  431. X#   $progname
  432. X
  433. X$ABSOLUTE = -1;
  434. X
  435. Xsub rslink {
  436. X    $debug && warn "$progname: DB: rslink @_\n";
  437. X
  438. X    local($todest,$tosource,$depth) = @_;
  439. X    local($d,$s,$f,$fromdst,$newdepth,@dir,@components);
  440. X
  441. X    if ($depth == $ABSOLUTE) {    # Using absolute paths
  442. X        $newdepth = $depth;    # Continue using them
  443. X        $fromdst = "";
  444. X    } else {            # Relative paths
  445. X        $newdepth = $depth + 1;
  446. X        $fromdst = "../" x $depth;
  447. X    }
  448. X
  449. X    # Get last component of directory name
  450. X    # and check whether we should ignore it.
  451. X
  452. X    @components = split ('/', $tosource);
  453. X    $f = @components[$#components];
  454. X    &should_omit ($f, $tosource) && return;
  455. X
  456. X    # Create destination directory,
  457. X    # unless we are only updating and it exists already.
  458. X
  459. X    if (-e $todest) {
  460. X        unless (-d _ && $opt_u) {    # The only good combination
  461. X            # All others die
  462. X            -d _ && die "$progname: $todest directory "
  463. X                    . "exists already (see -u option)\n";
  464. X            $opt_u && die "$progname: Update failed: "
  465. X                    . "$todest is not a directory\n";
  466. X            die "$progname: $todest exists\n";
  467. X            # NOTREACHED
  468. X        }
  469. X        # (Destination directory exists already.)
  470. X    } else {
  471. X        $opt_v && print "mkdir $todest\n";
  472. X        unless (mkdir($todest, $dirmode)) {
  473. X            if ($! == $EEXIST) { # Assume NFS problem
  474. X                $opt_q || warn "$progname: mkdir $todest: $! "
  475. X                    . "-- IGNORING SPURIOUS ERROR\n";
  476. X            } else {    # Some other error
  477. X                die "$progname: Can't create directory "
  478. X                    . "$todest: $!\n";
  479. X            }
  480. X        }
  481. X    }
  482. X
  483. X    opendir(DIR, $tosource) || die "$progname: Can't open $tosource: $!";
  484. X    @dir = readdir(DIR);
  485. X    closedir(DIR);
  486. X
  487. X    FILE:
  488. X    foreach $f (@dir) {
  489. X
  490. X        # Discard irrelevant directory entries
  491. X        ($f eq "." || $f eq "..") && next FILE;
  492. X
  493. X        $s = $tosource . "/" . $f;    # Full source path name
  494. X        $d = $todest . "/" . $f;    # Full destination path name
  495. X
  496. X        # If the file is a symbolic link
  497. X        #   (and not ignorable, and destination does not exist)
  498. X        #   if $opt_r and relative symblink, copy contents
  499. X        #   elsif $opt_r and absolute symblink, copy contents
  500. X                #   else make link to link
  501. X        # elsif the file is a directory
  502. X        #   recurse (to create dir and contents, unless ignorable)
  503. X        # else
  504. X        #   make symbolic link
  505. X        #   (unless ignorable or exists already)
  506. X
  507. X        if (-l $s) {
  508. X            &should_omit ($f, $s) && next FILE;
  509. X            # Unless $opt_u, the directory was newly
  510. X            # created so should be empty -- so it
  511. X            # shouldn't contain any files -- unless some
  512. X            # other program has created a file meanwhile.
  513. X            if (-e $d) {
  514. X                die "$progname: $d exists already\n"
  515. X                    unless ($opt_u);
  516. X            } else {    # Create a link
  517. X                $spath = $fromdst . $s;
  518. X                # Maybe we are treating symblinks specially
  519. X                if ($opt_r || $opt_s) {
  520. X                    # Some sorts of link-to-links special
  521. X                    # Check type of link
  522. X                    $link = (readlink ($s) ||
  523. X                        die ("$progname: Can't read "
  524. X                            ."link $s: $!\n"));
  525. X                    if ($link =~ m|^/|) {
  526. X                        # It is an absolute link
  527. X                        $opt_s    ? &dolink ($link, $d)
  528. X                            : &dolink ($spath, $d);
  529. X                    } else {
  530. X                        # It is a relative link
  531. X                        $opt_r    ? &dolink ($link, $d)
  532. X                            : &dolink ($spath, $d);
  533. X                    }
  534. X                } else { # No special link treatment
  535. X                    &dolink ($spath, $d);
  536. X                }
  537. X            }
  538. X        } elsif (-d $s) {    # It's a directory
  539. X            &rslink($d, $s, $newdepth);
  540. X        } else {        # It's something else
  541. X            &should_omit ($f, $s) && next FILE;
  542. X            if (-e $d) {
  543. X                die "$progname: $d exists already\n"
  544. X                    unless ($opt_u);
  545. X            } else {    # Create a link
  546. X                $spath = $fromdst . $s;
  547. X                &dolink ($spath, $d);
  548. X            } 
  549. X        }
  550. X    }
  551. X}    
  552. X
  553. X######################################################################
  554. X#
  555. X# Main program
  556. X#
  557. X
  558. X# A few checks
  559. X
  560. X-r $fromdir || die "$progname: Can't read $fromdir\n";
  561. X-d $fromdir || die "$progname: $fromdir is not a directory\n";
  562. X
  563. X$debug && warn "$progname: DEBUGGING MODE\n";
  564. X
  565. Xif ($opt_a) {    # Don't automatically find ancestor
  566. X    # Remove any `/' from directory names
  567. X    chop $todir if (substr($todir, -1) eq "/");
  568. X    chop $fromdir if (substr($fromdir, -1) eq "/");
  569. X
  570. X    if ($fromdir =~ m|^/|) {    # Create absolute symlinks (via root)
  571. X
  572. X        # Make absolute symbolic links
  573. X
  574. X        &rslink($todir, $fromdir, $ABSOLUTE);
  575. X
  576. X    } else {        # Create symlinks via cwd
  577. X
  578. X        unless ($opt_q) {
  579. X            # Check whether todir path contains symbolic links
  580. X
  581. X            @todir = split(/\//, $todir);
  582. X
  583. X            # Perl wierdness?  If foo is a symbolic link
  584. X            # to a directory, then -l "foo" && -d "foo" is
  585. X            # true, but -l "foo/" is false.  Maybe not
  586. X            # perl; ls does the same.
  587. X
  588. X            $nextdir = ".";
  589. X            foreach $dir (@todir) {
  590. X                $nextdir .= "/" . $dir;
  591. X                -l $nextdir && warn ("$progname: Warning: "
  592. X                    . " $nextdir is a symbolic link\n");
  593. X            }
  594. X        }
  595. X
  596. X        &rslink($todir, $fromdir, $#todir + 1);
  597. X    }
  598. X} else {
  599. X    # Do relative symbolic link via common ancestor
  600. X
  601. X    # Work out path from destination to source:
  602. X    #   canonicalize the paths
  603. X    #   ignore common initial directories
  604. X    #   add "../"s to get back to common starting point
  605. X
  606. X    # Canonicalize names with cd $path; pwd
  607. X    # It might be better to remember the current directory with
  608. X    # pwd and then use chdir; or to fork.
  609. X
  610. X    open (FROMDIR, "cd $fromdir; pwd|")
  611. X        || die "$progname: Can't find absolute path of $fromdir\n";
  612. X    $fromdir = <FROMDIR>;
  613. X    chop $fromdir;
  614. X
  615. X    # We can't cd to $todir since it may not exist yet,
  616. X    # so cd to the parent.
  617. X
  618. X    $todir =~ m|[^/]*$|;    # Match last component
  619. X    $tonewdir = $&;
  620. X    $toparent = $` || ".";    # Supply "." if $todir is simple name
  621. X    $toparent_saved = $toparent;
  622. X
  623. X    open (TODIR, "cd $toparent; pwd|")
  624. X        || die "$progname: Can't find absolute path of " . 
  625. X            "$toparent_saved\n";
  626. X    $toparent = <TODIR>;
  627. X    defined ($toparent) 
  628. X        || die "$progname: Can't find absolute path of "
  629. X            . "$toparent_saved\n";
  630. X    chop $toparent;
  631. X
  632. X    # Now work out relative path from dir2 (dest) to dir1 (source)
  633. X
  634. X    # Delete leading '/' from path names
  635. X
  636. X    substr($fromdir,0,1) = "";
  637. X    substr($toparent,0,1) = "";
  638. X
  639. X    # Split into directory names
  640. X
  641. X    @fromdir = split(/\//, $fromdir);
  642. X    @toparent = split(/\//, $toparent);
  643. X
  644. X    # Remove common initial path
  645. X
  646. X    while (@fromdir != 0 && @toparent != 0
  647. X        && $fromdir[0] eq $toparent[0]) {
  648. X        shift(@fromdir);
  649. X        shift(@toparent);
  650. X    }
  651. X
  652. X    # Sensible arguments?
  653. X
  654. X    (@fromdir == 0)
  655. X        && die "$progname: Won't link child to parent directory\n";
  656. X
  657. X    # For every remaining component in toparent, we have to go up
  658. X
  659. X    $rel = "../" x @toparent;
  660. X
  661. X    # Join on rest of fromdir
  662. X
  663. X    if (@fromdir != 0) {
  664. X        $rel .= join("/", @fromdir);
  665. X    }
  666. X
  667. X    $opt_v && print "cd /$toparent\n";
  668. X    chdir "/".$toparent || die "$progname: Can't cd to /$toparent: $!\n";
  669. X    &rslink($tonewdir, $rel, 1);
  670. X}
  671. X
  672. X# End of rslink
  673. END_OF_rslink
  674. if test 12446 -ne `wc -c <rslink`; then
  675.     echo shar: \"rslink\" unpacked with wrong size!
  676. fi
  677. chmod +x rslink
  678. # end of overwriting check
  679. fi
  680. if test -f rslink.1 -a "${1}" != "-c" ; then 
  681.   echo shar: Will not over-write existing file \"rslink.1\"
  682. else
  683. echo shar: Extracting \"rslink.1\" \(6062 characters\)
  684. sed "s/^X//" >rslink.1 <<'END_OF_rslink.1'
  685. X.\" Last edited: Fri May 21 10:19:55 1993 by Tim Wilson
  686. X.\" There is an ident at the end of this man page.
  687. X.TH RSLINK 1 "Release 1.20" "Tim Wilson's commands"
  688. X.SH NAME
  689. Xrslink \- Recursive symbolic link (relative or absolute)
  690. X.SH SYNOPSIS
  691. X.B rslink
  692. X[
  693. X.B -a
  694. X] [
  695. X.B -q
  696. X] [
  697. X.B -r
  698. X] [
  699. X.B -s
  700. X] [
  701. X.B -u
  702. X] [
  703. X.B -v
  704. X]
  705. X.I fromdir todir
  706. X[ 
  707. X.I ignore ...
  708. X]
  709. X.SH DESCRIPTION
  710. X.B Rslink
  711. Xcreates a shadow directory tree:
  712. Xa replica of the source directory tree structure, populated with symbolic
  713. Xlinks to the original non-directory files.
  714. X.PP
  715. XShadow trees are useful, for example, 
  716. X.IP \(bu
  717. Xfor compiling a source tree for several architectures (each has its
  718. Xown shadow tree of the sources), and
  719. X.IP \(bu
  720. Xin shared development by several programmers from a set of master
  721. Xsources:  each developer makes local
  722. Xcopies only of files he wishes to modify.
  723. X.PP
  724. XRelative symbolic links are useful because they are still valid if the tree
  725. Xrooted at the common ancestor is moved.
  726. X.PP
  727. X.I
  728. XWhy use rslink?
  729. X.B Rslink
  730. Xis much faster than similar shell scripts.  How much faster
  731. Xdepends on the speed of your discs and file servers.
  732. X.PP
  733. X.B Rslink
  734. Xcreates a copy of the existing directory tree rooted at directory 
  735. X.IR fromdir .
  736. XThe root of the new directory tree is the new directory
  737. X.IR todir .
  738. X.I Todir
  739. Xshould not exist already
  740. X(unless the
  741. X.B \-u
  742. Xoption is given).
  743. XThe
  744. X.I todir
  745. Xtree
  746. Xcontains a symbolic link back to every non-directory under
  747. X.IR fromdir ,
  748. Xexcept that the
  749. X.BR \-r " and " \-s
  750. Xoptions cause
  751. X.B rslink
  752. Xto copy the contents of links rather than make links to links (see
  753. X.SM OPTIONS
  754. Xfor details).
  755. X.PP
  756. X.B Rslink 
  757. Xcan create several styles of link:
  758. X.IP \(bu
  759. XRelative symbolic links via the common ancestor directory of
  760. X.I fromdir
  761. Xand
  762. X.IR todir .
  763. XThis is the default.
  764. X.IP \(bu
  765. XAbsolute symbolic links\(emthe contents of the symbolic link is a
  766. Xabsolute pathname starting from the root directory 
  767. X.RB ` / '.
  768. XThis style of link is created under the
  769. X.B \-a
  770. Xoption when
  771. X.I fromdir
  772. Xis an absolute pathname (starts with
  773. X.RB ` / ').
  774. X.IP \(bu
  775. XRelative symbolic links via the current working directory.
  776. XThis style of link is created under the 
  777. X.B \-a
  778. Xoption when 
  779. X.I fromdir
  780. Xis a relative path.
  781. X.IP \(bu
  782. XThe
  783. X.BR \-r " and " \-s
  784. Xoptions tell
  785. X.B rslink
  786. Xnot to make symbolic links to symbolic links, 
  787. Xbut instead to copy the contents of relative
  788. X.RB ( \-r )
  789. Xor absolute
  790. X.RB ( \-s )
  791. Xsymbolic links (see below).
  792. X.PP
  793. XThe optional arguments
  794. X.I ignore ...
  795. Xare
  796. X.BR perl (1)
  797. Xregular expressions.
  798. XAny file or directory name from the source tree that matches any of the
  799. Xregular expressions will be ignored by 
  800. X.BR rslink .  
  801. XThe regular expressions are matched against the final,
  802. Xfile name component, not the whole path.
  803. X.SH OPTIONS
  804. X.TP
  805. X.B \-a
  806. XDo not make links via the first common ancestor directory.  
  807. X.IP
  808. XIf
  809. X.I fromdir
  810. Xis an absolute pathname, then the links will contain absolute
  811. Xpathnames. 
  812. X.IP
  813. XIf 
  814. X.I fromdir
  815. Xis a relative pathname, then the link will be a relative link via
  816. Xthe current working directory. 
  817. XThis option may be useful if 
  818. X.I fromdir
  819. Xand
  820. X.I todir
  821. Xare on different file systems, and 
  822. X.I fromdir
  823. Xcontains a symbolic link from
  824. X.IR todir 's
  825. Xfile system to
  826. X.IR fromdir 's
  827. Xfile system.
  828. XIf
  829. X.I todir
  830. Xcontains a symbolic link, 
  831. X.B rslink
  832. Xwill issue a warning (see
  833. X.SM DIAGNOSTICS 
  834. Xbelow).  
  835. XThe resulting link may not point where you expect, since 
  836. X.B dir/..
  837. Xis not (in general) the current directory if
  838. X.B dir
  839. Xis a symbolic link to a directory.
  840. X.TP
  841. X.B \-q
  842. XBe quiet; suppress warning messages.
  843. X.TP
  844. X.B \-r
  845. XCopy the contents of relative symbolic links from the source tree,
  846. Xrather than linking to them.  A symbolic link is relative if its
  847. Xcontents do not start with 
  848. X.RB ` / '.
  849. XThis option is useful if the source tree
  850. Xcontains relative links to other parts of the source tree, and you
  851. Xwant the corresponding files in the shadow tree to refer to other
  852. Xfiles in the shadow tree rather than back to the source tree.
  853. X.TP
  854. X.B \-s
  855. XCopy the contents of absolute symbolic links from the source tree,
  856. Xrather than linking to them.  A symbolic link is absolute if its
  857. Xcontents starts with
  858. X.RB ` / '.
  859. X.TP
  860. X.B \-u
  861. XUpdate the shadow tree.
  862. X.B Rslink
  863. Xonly creates directories and links files that do
  864. Xnot exist already in the shadow tree.
  865. XIt is an error if a directory in the source tree is a non-directory
  866. Xfile in the shadow tree.
  867. X.TP
  868. X.B \-v
  869. XSelect verbose mode.  In verbose mode,
  870. X.B rslink
  871. Xprints messages describing its actions and  files matching the
  872. X.I ignore
  873. Xlist.
  874. X.SH DIAGNOSTICS
  875. X.TP
  876. X.B "mkdir \fIdirectory:\fP file exists -- IGNORING SPURIOUS ERROR"
  877. X.TP
  878. X.B "symlink \fIfile1\fP -> \fIfile1\fP: file exists -- IGNORING SPURIOUS ERROR"
  879. XThese messages may occur only when creating links on 
  880. X.SM NFS 
  881. Xfile systems.
  882. XThey are due to problems with the 
  883. X.SM NFS
  884. Xprotocol and non-idempotent
  885. Xoperations (such as
  886. X.BR symlink (2)
  887. Xand 
  888. X.BR mkdir (2)).
  889. X.TP
  890. X.B "rslink: Warning: \fIdirectory\fP is a symbolic link"
  891. XThis warning occurs under the
  892. X.B \-a
  893. Xoption if any element of the path
  894. X.I todir
  895. Xis a symbolic link.
  896. X.PP
  897. XYou will get an error message from 
  898. X.B perl
  899. Xif an
  900. X.I ignore
  901. Xregexp is invalid.
  902. X.SH BUGS
  903. X.B Rslink
  904. Xalways creates directories with mode 0755.
  905. X.PP
  906. X.I The value of
  907. X.SM EEXIST
  908. Xis hard-coded into
  909. X.B rslink
  910. X(as 17).
  911. X.SH SEE ALSO
  912. Xln(1),
  913. Xown(1L),
  914. Xperl(1),
  915. Xsymlink(2)
  916. X.SH AUTHOR
  917. XTim Wilson, Rank Xerox Cambridge EuroPARC, UK
  918. X.RI ( wilson@europarc.xerox.com ).
  919. XOriginally written by the author while at the University of Cambridge
  920. XComputer Laboratory, UK
  921. X.RI ( tdw@cl.cam.ac.uk ).
  922. X.PP
  923. X.SH COPYRIGHT
  924. XCopyright (C) 1992, 1993 T D Wilson.  All rights reserved.
  925. XPermission to copy without fee all or part of this material is granted
  926. Xprovided that the copies are not made or distributed for direct
  927. Xcommercial advantage, the copyright notice and the title and date
  928. Xappear, and notice is given that copying is by permission of the
  929. Xauthor.  To copy otherwise, or to republish, requires specific
  930. Xpermission.  
  931. XT\ D\ Wilson makes no representations about the suitability
  932. Xof this software for any purpose.  It is provided ``as is'' without
  933. Xexpress or implied warranty.
  934. X.PP
  935. X$Id: rslink.1,v 0.5 1993/05/21 09:20:05 wilson Exp $
  936. END_OF_rslink.1
  937. if test 6062 -ne `wc -c <rslink.1`; then
  938.     echo shar: \"rslink.1\" unpacked with wrong size!
  939. fi
  940. # end of overwriting check
  941. fi
  942. echo shar: End of archive 1 \(of 1\).
  943. cp /dev/null ark1isdone
  944. MISSING=""
  945. for I in 1 ; do
  946.     if test ! -f ark${I}isdone ; then
  947.     MISSING="${MISSING} ${I}"
  948.     fi
  949. done
  950. if test "${MISSING}" = "" ; then
  951.     echo You have unpacked all 1 archives.
  952.     rm -f ark[1-9]isdone
  953. else
  954.     echo You still need to unpack the following archives:
  955.     echo "        " ${MISSING}
  956. fi
  957. ##  End of shell archive.
  958. exit 0
  959.  
  960. exit 0 # Just in case...
  961.