lln - a routine to list all links to a file

Paul K Heffner heff at bsdpkh.UUCP
Wed Dec 31 06:23:16 AEST 1986


This little routine will list out all paths to a file. (A list of all
links). I suspect it is terribly System V dependant and I welcome
anybody's converting it for other systems. It seems to run really
well on most System V boxes...

Paul Heffner
AT&T-IS, Altamonte Springs, FL.
(305)-869-2245
{ihnp4,akgua,attmail}!bsdpkh!heff

======================= Cut here and send rest thru sh ===============
#!bin/sh
# shar: Shell Archiver
#	Run the following text with /bin/sh to create:
#		Readme
#		lln.1
#		lln.c
#
echo shar: extracting Readme '(1420 characters)'
sed 's/^XX//' << \SHAR_EOF > Readme
XX		=========== Readme file for lln ==========
XX
XX
XXThis little terror searches through a file system like a juggernaut,
XXlooking for all links to the files in his arg list. I wrote it because
XXncheck is a pain to use and I really felt like doing it. I have been
XXusing it for some time now with no problems so I feel it's pretty stable.
XX
XX
XXBuilding lln:
XX
XXMake's internal rules should be sufficient to build lln. Just type
XX"make lln". If that fails use "cc -O -olln lln.c".
XX
XXDependencies:
XX
XXLln has been compiled and runs fine on the following AT&T System V
XXmachines: 6300+ (small model under simultask), 3b1/7300, 3b2(all), 
XX3b5 and 3b15. With no BSD system at my disposal, I didn't include
XXany IFDEFs for BSD and I suspect it would fail to compile under same.
XXI would be delighted to see what would need to be changed for lln
XXto run under BSD systems or Xenix, etc. (Probable trouble areas:
XXuse of /etc/mnttab, stat calls)
XX
XXUsage rights:
XX
XXI wrote this routine to fill a technical need, not a financial one. Use
XXit however you want and give it to anyone who needs it. (I'd appreciate
XXsome credit, but I don't really care!!)
XX
XXContact info:
XX
XXlln was scratched together during spare time by me:
XX
XXPaul Heffner
XXATT Info Systems 78Q-611
XX1024 Wymore Rd.
XXAltamonte Springs, FL.  32714
XX
XX(305)-869-2245			(I.S. Comm RNX 755)
XX{ihnp4,akgua,attmail}!bsdpkh!heff
XX
XXComments, coding suggestions, and technical errata are solicited and welcome!
XX
SHAR_EOF
if test 1420 -ne `wc -c Readme`
then
	echo shar: error transmitting Readme 'expected 1420 characters'
fi
echo shar: extracting lln.1 '(1015 characters)'
sed 's/^XX//' << \SHAR_EOF > lln.1
XX.deTH
XX.PD
XX.nrIN \\n()Mu
XX.ift .ds ]H \\$1\^(\^\\$2\^)
XX.ifn .ds ]H \\$1(\\$2)
XX.if\\n()s .ds ]D
XX.if\\n()t .ds ]D UNIX System V
XX.ifn .ds ]D UNIX System V
XX.ds]L
XX.if!\\$3 .ds ]L (\^\\$3\^)
XX.if!\\$4 .ds ]D \\$4
XX.wh0 }H
XX.wh-\\n(:mu }F
XX.em}M
XX.if\\n(nl .bp
XX.nr)I \\n()Mu
XX.nr)R 0
XX.}E
XX.DT
XX.ifn \{.na
XX.nh\}
XX.ift \{.bd S 3 3
XX.hy14 \}
XX..
XX.TH LLN 1
XX.SH NAME
XXlln \- list all paths to a file
XX.SH SYNOPSIS
XX.B lln
XXfile names..
XX.SH DESCRIPTION
XX.I Lln\^
XXattempts to list the complete paths for all links to the given file
XXnames. The paths are printed on
XX.I stdout,
XXeach path separated by a newline. The order of the list is simply the
XXorder in which each link was found during a recursive file system search.
XX.SH BUGS/LIMITATIONS
XXThe file system search opens a new file descriptor for each sub-directory
XXdescent. The search will halt if directory nesting level exceeds the
XXmaximum open files per process. (NOFILE tunable parameter on later System
XXV releases, 20 on older) 
XX.SH FILES
XX/etc/mnttab
XX.SH SEE ALSO
XXncheck(1m),
XXmnttab(4).
SHAR_EOF
if test 1015 -ne `wc -c lln.1`
then
	echo shar: error transmitting lln.1 'expected 1015 characters'
fi
echo shar: extracting lln.c '(3808 characters)'
sed 's/^XX//' << \SHAR_EOF > lln.c
XX#include <sys/types.h>
XX#include <sys/dir.h>
XX#include <sys/stat.h>
XX#include <stdio.h>
XX#include <fcntl.h>
XX#include <mnttab.h>
XX
XX
XX/*
XX	lln: list links for files
XX
XX	not (c) 1986 Paul Heffner @ AT&T-IS Altamonte Springs, FL.
XX		 use it however you wish.
XX
XX	Enquiries, advice, and calm criticism to:
XX
XX	ihnp4   \
XX	akgua   - bsdpkh!heff
XX	attmail /
XX*/
XX
XX#define MTE_SIZE	sizeof(struct mnttab)
XX#define DIRESIZ		sizeof(struct direct)
XX#define PATHMAX	512
XX
XXextern int errno;
XX
XX/*
XX	program globals
XX*/
XXstatic int inn;		/* inode number of file being searched for... */
XXstatic int found;	/* count of found directory entries.. */
XXstatic int need;	/* count of directory entries to find.. */
XXstatic int curdev;	/* device # of disk holding fs of objective file. */
XXstatic char pathbuf[PATHMAX];	/* holds current search path */
XX
XXmain(argc,argv)
XXint argc;
XXchar **argv;
XX{	static char *mtfil = "/etc/mnttab";
XX	struct stat ssfil, ssfs;
XX	struct mnttab mte;
XX	int i, mth, dirfd, x;
XX
XX	if (argc < 2) exit(0);
XX
XX	fclose(stdin);	/* free up an extra fd (just in case) */
XX
XX	if ((mth = open(mtfil,O_RDONLY)) == -1)
XX	{	fprintf(stderr,"%s: errno %d, cannot open %s\n",argv[0],errno,mtfil);
XX		exit(16);
XX	}
XX	for (i = 1; i < argc; ++i)
XX	{
XX		if (stat(argv[i],&ssfil))
XX		{	fprintf(stderr,"%s:errno %d can not access %s\n",argv[0],errno,argv[i]);
XX			continue;
XX		}
XX		if ((ssfil.st_mode & S_IFMT) == S_IFDIR)
XX		{	fprintf(stderr,"%s: %s is a directory file.\n",argv[0],argv[i]);
XX			continue;
XX		}
XX		inn = ssfil.st_ino;	/* establish search inode number */
XX		found = 0;		/* set count of # found */
XX		need = ssfil.st_nlink;	/* set count of # of links */
XX		curdev = ssfil.st_dev;	/* # of device holding file */
XX
XX/*
XX	Scratch through mount table looking for fs hosting file
XX	seeking a match on device number...
XX*/
XX
XX		for (x = 0; x < NMOUNT; ++x)
XX		{	if (read(mth,&mte,MTE_SIZE) != MTE_SIZE)
XX			{	fprintf(stderr,"%s: errno %d reading mnttab\n",argv[0],errno);
XX				exit(32);
XX			}
XX			stat(mte.mt_filsys,&ssfs);
XX			if (ssfs.st_dev == ssfil.st_dev) break;
XX		}
XX
XX/*
XX	The path name is constructed in 'pathbuf'.
XX	We start with mounted directory from /etc/mnttab entry...
XX*/
XX		strncpy(pathbuf,mte.mt_filsys,14);
XX		if (pathbuf[1] == '\0') pathbuf[0] = '\0';	/* special case for root fs (avoids // at front of path) */
XX		chdir(mte.mt_filsys);
XX		if ((dirfd = open(mte.mt_filsys,O_RDONLY)) == -1)
XX		{	fprintf(stderr,"%s: errno %d opening %s\n",argv[0],errno,mte.mt_filsys);
XX			exit(-1);
XX		}
XX		if (lnsrch(dirfd))
XX			fprintf(stderr,"%s incomplete list: only %d of %d links were found.\n",argv[0],found,need);
XX		close(dirfd);
XX
XX		lseek(mth,0L,0);	/* reset to beginning of mnttab */
XX	}
XX	close(mth);
XX	exit(0);
XX}
XX
XXlnsrch(dirfd)
XXint dirfd;
XX{	struct stat curf;
XX	struct direct cd;
XX	int newdfd;
XX	char *pathend;
XX
XX	lseek(dirfd,DIRESIZ << 1,0);	/* go past . and .. */
XX	while (read(dirfd,&cd,DIRESIZ))
XX	{	if (!cd.d_ino) continue;	/* skip empty entries (i = 0) */
XX		if (stat(cd.d_name,&curf))
XX		{	fprintf(stderr,"error - cannot stat %s/%s\n",pathbuf,cd.d_name);
XX			continue;
XX		}
XX		if ((curf.st_mode & S_IFMT) == S_IFDIR)	/* sub-dir?? */
XX		{
XX/*
XX	ignore MT directories and keep search to objective fs (dev)
XX*/			if (curf.st_size == 32 ||
XX			    curf.st_dev != curdev) continue;
XX
XX			if ((newdfd = open(cd.d_name,O_RDONLY)) == -1)
XX			{	fprintf(stderr,"error -cannot visit %s/%s\n",pathbuf,cd.d_name);
XX				continue;
XX			}
XX/*
XX	Maintain current path in pathbuf global area
XX*/
XX			for (pathend = pathbuf; *pathend; ++pathend) ;
XX			*pathend = '/';
XX			strncpy(pathend + 1,cd.d_name,14);
XX			chdir(cd.d_name);
XX			if (!lnsrch(newdfd)) return 0;	/* recursively return 0 if all were found */
XX			close(newdfd);
XX			chdir("..");
XX			*pathend = '\0';
XX			continue;
XX		}
XX		if (cd.d_ino == inn)	/* Print out path on match!! */
XX		{	printf("%s/%.14s\n",pathbuf,cd.d_name);
XX			if (++found == need) return 0;
XX		}
XX	}
XX	return -1;
XX}
SHAR_EOF
if test 3808 -ne `wc -c lln.c`
then
	echo shar: error transmitting lln.c 'expected 3808 characters'
fi



More information about the Comp.sources.unix mailing list