Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!gatech!akgua!codas!bsdpkh!heff From: heff@bsdpkh.UUCP (Paul K Heffner) Newsgroups: net.sources Subject: lln - a routine to list all links to a file Message-ID: <263@bsdpkh.UUCP> Date: Tue, 30-Dec-86 15:23:16 EST Article-I.D.: bsdpkh.263 Posted: Tue Dec 30 15:23:16 1986 Date-Received: Wed, 31-Dec-86 20:36:34 EST Organization: AT&T-IS (SDSS), Orlando Fl. Lines: 278 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#includeXX#include XX#include XX#include XX#include XX#include 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