[comp.unix.questions] Finding links

doug@cogent.UUCP (Doug Perlich) (10/19/89)

This is more than likely a stupid question, but I'll ask it anyway, it's
one thing I'm good at.  (I did look into manuals, and no gurus around here.)

I ocasionally have problems working in large project groups when someone
has a link (using ln) to a file.  I can't find the file that the link(s) are
to.  (Different name, different directory).

For instance:
./xyz:
-rwxrwxr-x   2 george   us           24 Jul 21 10:57 ./xyz/foobar
-rwxrwxrwx   1 gorby    them        124 Oct 18 09:37 ./xyz/stoly

./abc:
-rwxrwxr-x   2 george   us           24 Jun 21 10:57 ./abc/foobee
-rwxrwxr-x   1 ronie    us          104 Jul  4 10:57 ./abc/huh?

Where the file foobar and foobee are linked together.

I might be located in directory xyz and I think "Hmm, I want to know what
the name of the link to the file foobar is".

I want to type "findthelinktothefile foobar"
and it will respond "/path1/path2/.../abc/foobee" and any other names
linked to the file.

Thanks
-Doug
g
g

ag@cbmvax.UUCP (Keith Gabryelski) (10/19/89)

In article <598@cogent.UUCP> SomeOne writes:
>I want to type "findthelinktothefile foobar"
>and it will respond "/path1/path2/.../abc/foobee" and any other names
>linked to the file.

All files are represented by something called an inode on disk.  When
you reference a file by its text name (ie /usr/myhome/foo) the kernel
actually interprets that into an number corresponding to an entry in a
table that is kept on disk.  This table has all the interesting
information about the file (its size, timestamps, where it is on the
disk and its 'link count').

The link count is the number of directory entries that point to this
inode.  There is a separate inode table for each partition, so file
links cannot span filesystems [*] since this would require unique
inode numbers for all files on all mounted partitions (filesystems).

Use 'ls -i FILENAME' to find the inode number of the file in question.
Then use 'find PATHNAME -inum INODE -print' to find all files with
inode INODE and start searching from the PATHNAME directory.  PATHNAME
should be the mount point directory of whatever filesystem FILENAME
was on (You can use 'df filename' on some systems to find this out, or
you may have to use 'df' and figure it out yourself).

Note: PATHNAME could also be '/' but then find(1) will show all files
with the same inode number even if the are on separate partitions
(which isn't what you want, since these files are not the same).

So, for example:

# I want to find all the file names for the inode corresponding to
# the file $HOME/aen.c.
#
$ ls -i $HOME/aen.c
    38 /z/unix/ag/aen.c
#
# 38 is the inode number for /z/unix/ag/aen.c.  Lets find the
# mount point directory.
#
$ pwd
$ /z/unix/ag
$ df .
Filesystem   Total    kbytes   kbytes   %     
node         kbytes   used     free     used  Mounted on
/dev/hp2c     113863   86316   16161    84%   /z
#
# So, we should start at /z since anything before it is not on the
# partition we are interested in (thus could not have a link
# coressponding to the file we are look for) [**]
#
$ find /z -inum 38 -print
/z/unix/ag/c/foo.c
/z/unix/ag/tmp/FOOBAR
/z/unix/ag/emd/amstr.c
/z/unix/ag/aen.c
#
# We are done.
#

Home this helps,
Pax, Keith

[*] Files can have links to files on other partitions, but this is
done through a mechanism call 'soft links' that may not exist on your
system (they exist on berkeley derived or sufficiently mutated SYSV
systems).  You can tell if a file is a soft link by doing an 'ls -l',
as:
$ ls -l /tmp/Aen.c
lrwxr-xr-x  1 ag              5 Oct 19 08:04 /tmp/Aen.c -> /z/unix/ag/aen.c
#
# Soft links are done in a entirely different way then 'hard links' so
# inode links don't come into play.
#

[**] It is possible that a filesystem could have been mounted on /z
somewhere.  This may have caused problems because of inode clashes.
-- 
 "It took no computation to dance to the rock 'n roll station" -- VU
  ag@cbmvax.commodore.com     Keith M. Gabryelski      ...!uunet!cbmvax!ag

rae98@wash08.uucp (Robert A. Earl) (10/19/89)

In article <598@cogent.UUCP> doug@cogent.UUCP (Doug Perlich) writes:
>I ocasionally have problems working in large project groups when someone
>has a link (using ln) to a file.  I can't find the file that the link(s) are
>to.  (Different name, different directory).
>I want to type "findthelinktothefile foobar"
>and it will respond "/path1/path2/.../abc/foobee" and any other names
>linked to the file.
>Thanks -Doug

My SVR2 system has a utility called 'ncheck':
ncheck - generate names from i-numbers
SYNOPSIS
/etc/ncheck [ -i numbers ]  [ -a ] [ -s ]  [ file-system ]

So you would use 'ls -li file_name'
to get the inode number of the file, then use
'/etc/ncheck -i inum_of_file_name /dev/dsk/cur_file_system'
to get a complete listing of the files in the current file
system which share the inode (ie are linked together).

This don't work for symbolic links, of course.
-- 
===========================================================
Name:	Bob Earl		Phone:	(202) 872-6018 (wk)
UUCP:	...!uunet!wash08!rae98	BITNET:	rae98@CAS

chris@mimsy.umd.edu (Chris Torek) (10/20/89)

# ln tumbolia tumbolia/tumbolia
			---famous last words of a new super user

In article <8222@cbmvax.UUCP> ag@cbmvax.UUCP (Keith Gabryelski) writes:
>So, for example:
># I want to find all the file names for the inode corresponding to
># the file $HOME/aen.c.

Just to be pedantic, I will claim that you do not want *all* the file
names (there are an infinite variety) but rather all the `canonical'
file names.  For instance, the file

	/ful/chris/bin/floop

on this machine also has the following (non-interesting) names:

	/ful/chris/bin/../bin/floop
	/ful/chris/tex/../bin/floop
	/ful/chris/./bin/floop
	/u/cvl/../zeke/../../ful/lost+found/../chris/tmp/../bin/././floop

(not to mention all the names rooted at the current directory!).

4.[234]BSD actually puts a limit on the number of possible file names,
by having a kernel define called `MAXPATHLEN' used during name->inode
translation, so that you have to `cd' into a deeply nested directory
to go any deeper (after which a number of utilities crap out, just like
SysV :-) ).
-- 
`They were supposed to be green.'
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

dold@mitisft.Convergent.COM (Clarence Dold) (10/20/89)

in article <598@cogent.UUCP>, doug@cogent.UUCP (Doug Perlich) says:

> I ocasionally have problems working in large project groups when someone
> has a link (using ln) to a file.  I can't find the file that the link(s) are
> to.  (Different name, different directory).

This shell script isn't smart enough to limit its output to the 
current filesystem, but it's cheap.

if [ $# = 1 ]
then
	TARGET=`/bin/ls -i $1|/usr/bin/cut -c1-5`
	if  [ $TARGET  ]
	then
		/bin/find / -inum $TARGET -print 2>/dev/null
	fi
else
	/bin/echo usage: $0 filenm
	exit 1
fi

-- 
---
Clarence A Dold - dold@tsmiti.Convergent.COM		(408) 434-5293
		...pyramid!ctnews!tsmiti!dold
		P.O.Box 6685, San Jose, CA 95150-6685	MS#10-007

perry@ccssrv.UUCP (Perry Hutchison) (10/20/89)

In article <598@cogent.UUCP> doug@cogent.UUCP (Doug Perlich) asks how to
find the other (link) names by which a file is known.

Many UNIX versions ago, there were a couple of programs called icheck and
ncheck which could help with this sort of thing.  They read the disk directly,
bypassing the file system.  They could be pretty slow if the disk was very
large.  (Their primary function, filesystem consistency checking and repair,
has since been taken over by fsck.)

The problem is that the file's inode contains the number of links which the
file has (this is the number which ls displays just ahead of the owner's
name), but it has no record of the links themselves.  In order to find the
file's other names, you have to determine its inode number and then search
every directory on the disk for other entries which point to that same inode.
(Unless you're looking for inconsistencies, you can stop as soon as the
number of links found equals the inode's link-count value.)

If you really need to do this, you can use 
  ls -i
to get the inode number, and then
  find volroot -xdev -inum #### -print
to scan the disk's directory tree and print the other names.

In the above, "volroot" refers to the directory on which the particular
filesystem's root directory is mounted and "####" is to be replaced by the
inode number obtained from ls -i.  On my system (SunOS, a BSD derivative),
-xdev tells find not to look at any filesystems which may be mounted within
the tree being scanned.  Check your man-page, as your mileage may vary, and
be aware that this technique will not find any links which may be located
in directories to which you don't have read permission.

[Flame-shield: Yes I know this can be reduced to a one-liner by piping the
result of ls through sed or cut, and including the result into the find
with ``.  I'm trying to keep it readable.  end of flame-shield]

So far, I've been assuming that you're only interested in "hard" links.  If
you need to find symbolic links also, another step is required:

  find / -type l -ls | fgrep -f linklist

where linklist is the file in which you've saved the list of names from the
previous find operation.  What this second find is doing is searching the
entire system for symbolic links (which, unlike hard links, need not be on
tha same filesystem with their target), doing the equivalent of an
"ls -gilds" on each, and then using fgrep to select from that list only
those entries which match one of the file's real names.

If the file has only one real name, it would be better to use grep so that
the match can be restricted to the end of the line.  It may be possible to
handle the multiple-name case, including end-of-line restriction, with egrep.

rae98@wash08.uucp (Robert A. Earl) (10/20/89)

In article <8222@cbmvax.UUCP> ag@cbmvax.UUCP (Keith Gabryelski) writes:
[ Long explanation about inodes and using 'find -inum' deleted
					      for the sake of brevity ]
>[*] Files can have links to files on other partitions, but this is
>done through a mechanism call 'soft links' that may not exist on your
>system (they exist on berkeley derived or sufficiently mutated SYSV
>systems).  You can tell if a file is a soft link by doing an 'ls -l',
>as:
>$ ls -l /tmp/Aen.c
>lrwxr-xr-x  1 ag              5 Oct 19 08:04 /tmp/Aen.c -> /z/unix/ag/aen.c
Just so you know, Keith, my "sufficiently mutated SYSV system" has
symbolic links (your 'soft links') (NCR Tower 32/650 SVR2), but the
output of 'ls -l' does not show this.  I am not claiming this is right
or wrong (personally, I like the BSD listing you showed...it is very
clear that not only is it a link, but it is linked to /z/unix/ag/aen.c),
just that it exists.
-- 
===========================================================
Name:	Bob Earl		Phone:	(202) 872-6018 (wk)
UUCP:	...!uunet!wash08!rae98	BITNET:	rae98@CAS

swc@griffin.uvm.edu (The Wheel in the Sky) (10/22/89)

in article  <598@cogent.UUCP> (Doug Perlich) writes:
>I might be located in directory xyz and I think "Hmm, I want to know what
>the name of the link to the file foobar is".

Given one path name of a file, find all other directories entries
pointing to the same file.  This means all directory entries with the
same inumber on the same file system as the given file name.

ncheck reports all the directory entries along with the inode they
point to.  You can also select just a certain inode to list pathnames
for.  Use ls -i to get the inumber for the file you want to
cross-reference.

A much slower method but one that doesn't require read access to the
special file uses find.  This also decends the fs tree to other
filesystems and across nfs mounts, but this can be prevented by cd'ing
to the mount point of the filesystem containing the file and by -xdev
option [-prune is documented but not yet implemented for SunOS4.0.3].

swc@kira>mkdir xyz abc
swc@kira>touch xyz/foobar
swc@kira>ln xyz/foobar abc/foobee
swc@kira>ls -i xyz/foobar
 15106 xyz/foobar
swc@kira>find . -inum 15106 -xdev -ls
15106    0 -rw-r--r--  2 root     daemon    0 Oct 21 23:54 ./xyz/foobar
15106    0 -rw-r--r--  2 root     daemon    0 Oct 21 23:54 ./abc/foobee
swc@kira>df xyz/foobar
Filesystem            kbytes    used   avail capacity  Mounted on
/dev/xd0h             494269  406091   38751    91%    /home
swc@kira>ncheck -a -i 15106 /dev/xd0h
/dev/xd0h:
15106   /tmp/xyz/foobar
15106   /tmp/abc/foobee

--
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Steve Chappelow         System TroubleShooter          EMBA Computer Facility  
(swc@uvm.edu || uunet!uvm-gen!swc)	               (802)656-2926

guy@auspex.auspex.com (Guy Harris) (10/26/89)

>[-prune is documented but not yet implemented for SunOS4.0.3].

Excuse me?  It has worked just fine since at least SunOS 3.0, and
possibly as far back as 2.0....

As the manual page indicates, it prunes the tree as soon as it is
executed, which means if you want to conditionally prune a tree, you
need some predicate to control when it will be executed; since there's
no "have I crossed a file system boundary" predicate, there's no way to
get the effect of "-xdev" with "-prune", but you *can*, for instance,
limit a "find" to locally-mounted file systems:

   find / -name .nfs\* -mtime +7 -exec rm -f {} \; -o -fstype nfs -prune

from the 4.0 "crontab".  (This may want to be modified in future
releases, since SunOS 4.1 will probably also support RFS, and S5R4 will
support NFS, RFS, "/proc", and a bunch of other file system types that
shouldn't be searched, and at least two types that should, namely S5 and
4.2BSD.)