[comp.sources.misc] v02i072: checklink - check for symlinks in limbo

jason@violet.berkeley.edu (Jason Venner) (03/10/88)

Submitted-By: "Jason Venner" <jason@violet.berkeley.edu>

Archive-Name: checklink


Comp.sources.misc: Volume 2, Issue 72
Submitted-By: "Jason Venner" <jason@violet.berkeley.edu>
Archive-Name: checklink

This is the first pass of a program that walks through the directories
listed on the command link, and prints out the names of the
unresolvable symbolic links, and what they point to on stdout.
Error messages are reported on stderr.
the exit code is the sum of the unresolved symbolic links + sum of non
fatal errors.
It has only tested on BSD systems.  [So how many non-BSD systems have symbolic
links?  ++bsa]

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-rw-rw-   1 allbery  uucp        3108 Mar  9 18:17 checklink.c
#
echo 'x - checklink.c'
if test -f checklink.c; then echo 'shar: not overwriting checklink.c'; else
sed 's/^X//' << '________This_Is_The_END________' > checklink.c
X#include	<stdio.h>
X#include	<sys/types.h>
X#include	<sys/dir.h>
X#include	<sys/stat.h>
X#include	<sys/file.h>
X
Xchar	*name;
X
Xmain( argc, argv )
Xint	argc;
Xchar	**argv;
X{
X
X	char	*dir;
X	char	*path;
X	char	cwd[MAXNAMLEN+1];
X	char*	getcwd();
X	char*	rindex();
X	int	err_count;
X
X	name = argv[0];
X	cwd[MAXNAMLEN] = '\0';
X	if( !getwd( cwd ) ) {
X		fprintf( stderr, "%s:unable to get current working directory, %s", name, cwd );
X		exit( 1 );
X	}
X	for( argc--, argv++, err_count = 0; argc; argc--, argv++ ) {
X		if( chdir( argv[0] ) == -1 ) {
X			fprintf( stderr, "%s:unable to chdir to %s\n", name, dir );
X			perror( "" );
X			err_count++;
X		}
X		if( (dir = rindex( argv[0], '/' )) ) {
X			*dir++ = '\0';
X			path = argv[0];
X		} else {
X			dir = argv[0];
X			path = ".";
X		}
X		err_count += check_link( dir, path );
X		if( chdir( cwd ) == -1 ) {
X			fprintf( stderr, "%s:unable to chdir to %s\n", name, cwd );
X			perror( "" );
X			exit( 2 );
X		}
X	}
X	exit( err_count );
X}
X
Xcheck_link( top, path )
Xchar	*top;
Xchar	*path;
X{
X
X	DIR	*dptr;
X	DIR*	opendir();
X	char	cwd[MAXNAMLEN+1];
X	char	link_name[MAXNAMLEN+1];
X	char*	sprintf();
X	extern	char	*name;
X	int	err_count;
X	int	link_size;
X	off_t	offset;
X	off_t	telldir();
X	struct	direct	*dent;
X	struct	direct*	readdir();
X	struct	stat	stat;
X
X	(void) sprintf( cwd, "%s/%s", path, top );
X	if( !(dptr = opendir( "." )) ) {
X		fprintf( stderr, "%s:unable to open directory %s", name, cwd );
X		perror( "" );
X		return 1;
X	}
X	if( !readdir( dptr )  || !readdir( dptr ) ) {
X		fprintf( stderr, "%s:unable to read '.' or '..' in %s\n",
X				  name, cwd );
X		perror( "" );
X		(void) closedir( dptr );
X		return 1;
X	}
X	err_count = 0;
X	link_name[MAXNAMLEN] = '\0';
X	while( (dent = readdir( dptr )) ) {
X		if( lstat( dent->d_name, &stat ) == -1 ) {
X			fprintf( stderr, "%s:unable to lstat %s/%s", name, cwd, dent->d_name );
X			perror( "" );
X			err_count++;
X			continue;
X		}
X		switch( stat.st_mode & S_IFMT ) {
X		case	S_IFDIR:
X			if( (offset = telldir( dptr )) == -1 ) {
X				fprintf( stderr, "%s:unable to telldir on %s\n", cwd );
X				perror( "" );
X				err_count++;
X				continue;
X			}
X			(void) closedir( dptr );
X			if( chdir( dent->d_name ) == -1 ) {
X				fprintf( stderr, "%s:unable to chdir to %s/%s", name, cwd, dent->d_name );
X				perror( "" );
X				return ++err_count;
X			}
X			err_count += check_link( dent->d_name, cwd );
X			if( chdir( ".." ) == -1 && chdir( cwd ) == -1 ) {
X				fprintf( stderr, "%s:unable to chdir up to %s", name, cwd);
X				return ++err_count;
X			}
X			if( !(dptr = opendir( "." )) ) {
X				fprintf( stderr, "%s:unable to reopendir %s", name, cwd );
X				perror( "" );
X				return ++err_count;
X			}
X			seekdir( dptr, offset, 0 );
X			break;
X		case	S_IFLNK:
X			if( (link_size = readlink( dent->d_name, link_name, MAXNAMLEN )) == -1 ) {
X				fprintf( stderr, "%s:unable to readlink on %s/%s", cwd, dent->d_name );
X				perror( "" );
X				err_count++;
X				continue;
X			}
X			link_name[link_size] = '\0';
X			if( access( link_name, F_OK ) == -1 ) {
X				printf( "%s/%s %s\n", cwd, dent->d_name, link_name );
X				err_count++;
X			}
X			break;
X		default:
X			break;
X		}
X	}
X	(void) closedir( dptr );
X	return err_count;
X}
________This_Is_The_END________
if test `wc -c < checklink.c` -ne 3108; then
	echo 'shar: checklink.c was damaged during transit (should have been 3108 bytes)'
fi
fi		; : end of overwriting check
exit 0