Initial revision
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* CHECKDVLNODE.C
|
||||
*
|
||||
* must be run from the top of an EPICS development node
|
||||
*
|
||||
* Reports to stdout:
|
||||
* Regular files in this node that are out-for-edit.
|
||||
* These are errors if uid doesn't agree.
|
||||
* Regular files in this node that should be links to epics
|
||||
* Links that point to a dest. outside of this node and the final
|
||||
* dest. is not in an EPICS node (Note: vw should be excluded).
|
||||
* Other Directories containing Regular files not under sccs control.
|
||||
* These directories should be manually checked for private
|
||||
* Imakefiles/Makefiles ...
|
||||
*
|
||||
* BUGS - only checks final destination of links.
|
||||
* if a link points outside of the current node
|
||||
* but the final real file/directory resides in epics
|
||||
* it is not reported. Then if it is changed in the outside
|
||||
* node you won't know it w/o running this tool again.
|
||||
*
|
||||
* distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* rcz
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
void procDirEntries();
|
||||
int processFile();
|
||||
int getRealEpicsPath();
|
||||
int checkLink();
|
||||
int dirwalk();
|
||||
int verbose;
|
||||
extern int errno;
|
||||
|
||||
#define BSIZE 128
|
||||
#define MAXMSG 256
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define SAME 0
|
||||
|
||||
static char pdot[] = "SCCS/p.";
|
||||
static char sdot[] = "SCCS/s.";
|
||||
static char msgbuff[MAXMSG];
|
||||
static caddr_t pEpics = (caddr_t)NULL;
|
||||
static caddr_t pDvl = (caddr_t)NULL;
|
||||
static int lenEpics;
|
||||
static int lenDev;
|
||||
|
||||
static char *dirList[] = {
|
||||
"share",
|
||||
"Unix",
|
||||
"Vx",
|
||||
"config",
|
||||
"release"
|
||||
};
|
||||
#define DIR_COUNT (sizeof(dirList) / sizeof(caddr_t))
|
||||
|
||||
/****************************************************************************
|
||||
MAIN PROGRAM
|
||||
****************************************************************************/
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *getcwd();
|
||||
char **pt;
|
||||
char name[20];
|
||||
int i;
|
||||
pt = dirList;
|
||||
if ((argc > 1) && ((strncmp(argv[1], "-v", 2)) == 0))
|
||||
verbose = TRUE;
|
||||
else
|
||||
verbose = FALSE;
|
||||
if ((pDvl = getcwd((char *)NULL, 128)) == NULL) {
|
||||
fprintf(stdout, "getcwd failed\n");
|
||||
return;
|
||||
}
|
||||
lenDev = strlen(pDvl);
|
||||
if ((getRealEpicsPath()) < 0 )
|
||||
return;
|
||||
fprintf(stdout, "\n\n\n%s:\nSTARTING SEARCH FROM NODE: %s\n",argv[0], pDvl);
|
||||
for (i = 0; i < DIR_COUNT; i++, pt++) {
|
||||
strcpy(name, *pt);
|
||||
fprintf(stdout, "Descending node --------------- %s\n",name);
|
||||
procDirEntries(name, name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/****************************************************************************
|
||||
GETREALEPICSPATH
|
||||
returns -1 - error, 0 - OK
|
||||
****************************************************************************/
|
||||
getRealEpicsPath()
|
||||
{
|
||||
caddr_t pt2;
|
||||
char resolved_path[MAXPATHLEN];
|
||||
|
||||
FILE *fp;
|
||||
char *epath_file = ".epicsShadowSrc";
|
||||
char epath[BSIZE];/* contents of 1st line of p.dot */
|
||||
|
||||
if ((fp = fopen(epath_file, "r")) == NULL) {
|
||||
fprintf(stdout, "checkDvlNode: can't fopen %s\n", epath_file);
|
||||
fprintf(stdout, "Probably not at root of shadow node\n");
|
||||
return(-1);
|
||||
}
|
||||
if ((fgets(epath, BSIZE, fp)) == NULL) {
|
||||
fprintf(stdout, "checkDvlNode: FATAL ERROR - reading %s\n", epath_file);
|
||||
return(-1);
|
||||
}
|
||||
fclose(fp);
|
||||
lenEpics = strlen(epath);
|
||||
if ( epath[lenEpics-1] == '\n' ) {
|
||||
epath[lenEpics-1] = '\0';
|
||||
}
|
||||
/* reset epics to real path if not on server */
|
||||
if(( pt2 = (caddr_t)realpath(epath, resolved_path)) == NULL) {
|
||||
fprintf(stdout, "FATAL ERROR - failed link component of %s=%s\n",
|
||||
epath, resolved_path);
|
||||
return (-1);
|
||||
}
|
||||
lenEpics = strlen(pt2);
|
||||
pEpics = (caddr_t)calloc(1,lenEpics+1);
|
||||
strcpy(pEpics,pt2);
|
||||
return(0);
|
||||
}
|
||||
/****************************************************************************
|
||||
PROCESSFILE
|
||||
for each regular file:
|
||||
if s.dot !exist - skip file
|
||||
if s.dot exist && p.dot !exist - print error
|
||||
else print dir file and contents of p.dot
|
||||
****************************************************************************/
|
||||
int
|
||||
processFile(name, dir, pfirstTime)
|
||||
char *name; /* regular file */
|
||||
char *dir; /* current directory */
|
||||
int *pfirstTime; /* ptr to firstTime flag*/
|
||||
{
|
||||
char sccsDir[MAXNAMLEN];
|
||||
char dotName[MAXNAMLEN];
|
||||
char *pbeg; /* beg of file pathname */
|
||||
char *pend; /* beg of filename */
|
||||
struct stat stbuf;
|
||||
struct stat lstbuf;
|
||||
FILE *fp;
|
||||
char ibuf[BSIZE];/* contents of 1st line of p.dot */
|
||||
int hasSccsDir = FALSE;
|
||||
|
||||
int len,
|
||||
j;
|
||||
pbeg = name;
|
||||
len = strlen(name);
|
||||
if (len + 7 > MAXNAMLEN) {
|
||||
fprintf(stdout, "processFile: pathname %s too long\n", name);
|
||||
return (0);
|
||||
}
|
||||
/* search for last slash '/' in pathname */
|
||||
for (j = len, pend = pbeg + len; j > 0; j--, pend--) {
|
||||
if (*pend == '/')
|
||||
break;
|
||||
}
|
||||
pend++; /* points to filename */
|
||||
/* determine if dir has an SCCS sub directory */
|
||||
strcpy(sccsDir, dir);
|
||||
strcat(sccsDir, "/SCCS");
|
||||
if (lstat(sccsDir, &lstbuf) == -1) {
|
||||
hasSccsDir = FALSE;
|
||||
} else
|
||||
hasSccsDir = TRUE;
|
||||
|
||||
if (!hasSccsDir) {
|
||||
if (!verbose) {
|
||||
if (*pfirstTime) {
|
||||
fprintf(stdout, "WARNING regular files in dir: %s\n", dir);
|
||||
*pfirstTime = FALSE;
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout, "WARNING regular file %s\n", name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* form p.dot name */
|
||||
strcpy(dotName, dir);
|
||||
strcat(dotName, "/");
|
||||
strcat(dotName, pdot);
|
||||
strcat(dotName, pend);
|
||||
if (stat(dotName, &stbuf) == -1) { /* no p.dot file */
|
||||
/* form s.dot name */
|
||||
strcpy(dotName, dir);
|
||||
strcat(dotName, "/");
|
||||
strcat(dotName, sdot);
|
||||
strcat(dotName, pend);
|
||||
if (stat(dotName, &stbuf) == -1) { /* no s.dot file */
|
||||
if (verbose) {
|
||||
fprintf(stdout, "WARNING regular file %s\n", name);
|
||||
}
|
||||
} else { /* has an s.dot */
|
||||
fprintf(stdout, "FATAL ERROR - file %s should be a link\n", name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((fp = fopen(dotName, "r")) == NULL) {
|
||||
fprintf(stdout, "processFile: can't fopen %s\n", dotName);
|
||||
return;
|
||||
}
|
||||
if ((fgets(ibuf, BSIZE, fp)) != NULL) {
|
||||
fprintf(stdout, "%-20s %-25s EDIT - %s", dir, pend, ibuf);
|
||||
} else
|
||||
fprintf(stdout, "FATAL ERROR - reading %s%s\n", pdot, pend);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
/****************************************************************************
|
||||
PROCDIRENTRIES
|
||||
process directory entries
|
||||
****************************************************************************/
|
||||
void
|
||||
procDirEntries(name, dir, pfirstTime)
|
||||
char *name; /* entry name */
|
||||
char *dir; /* current directory */
|
||||
int *pfirstTime; /* ptr to firstTime flag*/
|
||||
{
|
||||
struct stat stbuf;
|
||||
if (lstat(name, &stbuf) == -1) {
|
||||
fprintf(stdout, "procDirEntries: can't access %s\n", name);
|
||||
return;
|
||||
}
|
||||
if ((stbuf.st_mode & S_IFMT) == S_IFLNK) {
|
||||
checkLink(name);
|
||||
return;
|
||||
}
|
||||
if ((stbuf.st_mode & S_IFMT) == S_IFREG) {
|
||||
processFile(name, dir, pfirstTime);
|
||||
return;
|
||||
}
|
||||
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
|
||||
dirwalk(name, procDirEntries);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/****************************************************************************
|
||||
CHECKLINK
|
||||
checks valid symbolic link for EPICS
|
||||
****************************************************************************/
|
||||
int
|
||||
checkLink(path)
|
||||
char *path;
|
||||
{
|
||||
char resolved_path[MAXPATHLEN];
|
||||
caddr_t pt;
|
||||
/* skip any path with "/templates/" in it */
|
||||
if ((strstr(path,"/templates/")) != NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(( pt = (caddr_t)realpath(path, resolved_path)) == NULL) {
|
||||
fprintf(stdout, "FATAL ERROR - failed link component of %s=%s\n",
|
||||
path, resolved_path);
|
||||
return;
|
||||
}
|
||||
/* compare $epics or beg of shadow with beg of dest */
|
||||
/* if neither present in dest - fail */
|
||||
if (((strncmp(pEpics, resolved_path, lenEpics)) == SAME )
|
||||
|| ((strncmp(pDvl, resolved_path, lenDev)) == SAME )) {
|
||||
return;
|
||||
} else {
|
||||
fprintf(stdout,
|
||||
"FATAL ERROR - link '%s' must point to epics or shadow area\n\t dest='%s'\n",path,resolved_path);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/****************************************************************************
|
||||
DIRWALK applies a function to each file in a directory
|
||||
****************************************************************************/
|
||||
int
|
||||
dirwalk(dir, fcn)
|
||||
char *dir;
|
||||
void (*fcn) ();
|
||||
{
|
||||
char name[MAXNAMLEN];
|
||||
struct dirent *dp;
|
||||
DIR *dfd;
|
||||
int firstTime;
|
||||
if ((dfd = opendir(dir)) == NULL) {
|
||||
fprintf(stdout, "dirwalk: can't open %s\n", dir);
|
||||
return;
|
||||
}
|
||||
firstTime = TRUE;
|
||||
while ((dp = readdir(dfd)) != NULL) {
|
||||
if (strcmp(dp->d_name, ".") == 0
|
||||
|| strcmp(dp->d_name, "..") == 0)
|
||||
continue; /* skip self and parent */
|
||||
if (strlen(dir) + strlen(dp->d_name) + 2 > sizeof(name))
|
||||
fprintf(stdout, "dirwalk: name %s/%s too long\n",
|
||||
dir, dp->d_name);
|
||||
else {
|
||||
sprintf(name, "%s/%s", dir, dp->d_name);
|
||||
(*fcn) (name, dir, &firstTime);
|
||||
}
|
||||
}
|
||||
closedir(dfd);
|
||||
}
|
||||
Reference in New Issue
Block a user