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