heff@bsdpkh.UUCP (Paul K Heffner) (12/30/86)
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
amos@instable.UUCP (Amos Shapir) (01/01/87)
What's wrong with: set `ls -id file` find / -inum $1 -print It's much more portable than the given program, can limit the search to any dir instead of /, and is probably faster on most machines. The moral is: before writing your own utilities (or hacking the kernel as some budding gurus do), re-read the manual - you'll be surprised how many new and useful flags are in utilities you have been using daily! -- Amos Shapir National Semiconductor (Israel) 6 Maskit st. P.O.B. 3007, Herzlia 46104, Israel (011-972) 52-522261 amos%nsta@nsc 34.48'E 32.10'N
kimcm@olamb.UUCP (Kim Chr. Madsen) (01/02/87)
In article <659@instable.UUCP>, amos@instable.UUCP (Amos Shapir) writes: > What's wrong with: > > set `ls -id file` > find / -inum $1 -print > Well nothing, if you don't have more than one filesystem or don't care about references to files which have nothing in common with the file searched for! Don't forget that there is a separate inode table connected to each filesystem, if / (root) and /usr is on separate filesystems they both have the inode 2, but /usr is not a link to /. What you'll have to do to make this work is to identify the filesystem where the ``file'' is located and then make the find command start at that point. Best wishes for 1987 Kim Chr. Madsen
kdw1@sphinx.UUCP (01/04/87)
(I'm directing followups to net.sources.bugs, which I gather is what corresponds to net.sources.d under the new naming scheme...) In net.sources, in reference to the recently posted lln program (which lists all files linked to a particular file), amos@instable.UUCP (Amos Shapir) writes: >What's wrong with: > >set `ls -id file` >find / -inum $1 -print > >It's much more portable than the given program, can limit the search >to any dir instead of /, and is probably faster on most machines. >The moral is: before writing your own utilities [...] I have a few comments in support of the author and poster of lln. I am using System V on an AT&T 3B5. 1. Our man page for find does not list -inum as an option. I tried it anyway, and was surprised to find that it works as I expect it's supposed to. But it seems a bit harsh to blame the author of lln for not knowing about what is (for some SysV users, at least) an undocumented feature. 2. Lln may be non-portable, but assuming that the options of Unix utilities act the same way on different flavors of Unix is too. Witness the differences between SysV and BSD greps and awk, to name just a couple. 3. On my system, lln is 9 times as fast as the find -inum suggestion. 4. The find -inum suggestion doesn't work. I-nodes are only unique within a file-system. The find technique, if rooted at / as suggested, will find all files with the same i-node. This is not the same as finding all links to a file, which is what lln does. When I tried the code above on a file which I knew to have two links (and which lln properly reports), find listed the two files, plus three totallly different files from two other file systems! I've already found lln to be quite useful; thanks to the author! keith-- Keith Waclena BITNET: xrtkdw1@uchimvs1.bitnet University of Chicago UUCP: ...ihnp4!gargoyle!sphinx!kdw1 Graduate Library School