Blame lib/rdev.c

Packit 6f02de
/*
Packit 6f02de
 * rdev.c -- readdev() function for lsof library
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
Packit 6f02de
 * 47907.  All rights reserved.
Packit 6f02de
 *
Packit 6f02de
 * Written by Victor A. Abell
Packit 6f02de
 *
Packit 6f02de
 * This software is not subject to any license of the American Telephone
Packit 6f02de
 * and Telegraph Company or the Regents of the University of California.
Packit 6f02de
 *
Packit 6f02de
 * Permission is granted to anyone to use this software for any purpose on
Packit 6f02de
 * any computer system, and to alter it and redistribute it freely, subject
Packit 6f02de
 * to the following restrictions:
Packit 6f02de
 *
Packit 6f02de
 * 1. Neither the authors nor Purdue University are responsible for any
Packit 6f02de
 *    consequences of the use of this software.
Packit 6f02de
 *
Packit 6f02de
 * 2. The origin of this software must not be misrepresented, either by
Packit 6f02de
 *    explicit claim or by omission.  Credit to the authors and Purdue
Packit 6f02de
 *    University must appear in documentation and sources.
Packit 6f02de
 *
Packit 6f02de
 * 3. Altered versions must be plainly marked as such, and must not be
Packit 6f02de
 *    misrepresented as being the original software.
Packit 6f02de
 *
Packit 6f02de
 * 4. This notice may not be removed or altered.
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
Packit 6f02de
#include "../machine.h"
Packit 6f02de
Packit 6f02de
#if	defined(USE_LIB_READDEV)
Packit 6f02de
Packit 6f02de
# if	!defined(lint)
Packit 6f02de
static char copyright[] =
Packit 6f02de
"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
Packit 6f02de
static char *rcsid = "$Id: rdev.c,v 1.12 2008/10/21 16:13:23 abe Exp $";
Packit 6f02de
# endif	/* !defined(lint) */
Packit 6f02de
Packit 6f02de
#include "../lsof.h"
Packit 6f02de
Packit 6f02de
Packit 6f02de
_PROTOTYPE(static int rmdupdev,(struct l_dev ***dp, int n, char *nm));
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * To use this source file:
Packit 6f02de
 *
Packit 6f02de
 * 1. Define DIRTYPE as:
Packit 6f02de
 *
Packit 6f02de
 *	  #define DIRTYPE direct
Packit 6f02de
 *    or  #define DIRTYPE dirent
Packit 6f02de
 *
Packit 6f02de
 * 2. Define HASDNAMLEN if struct DIRTYPE has a d_namlen element, giving
Packit 6f02de
 *    the length of d_name.
Packit 6f02de
 *
Packit 6f02de
 * 3. Define the RDEV_EXPDEV macro to apply special handling to device
Packit 6f02de
 *    numbers, as required.  For example, for EP/IX 2.1.1:
Packit 6f02de
 *
Packit 6f02de
 *	#define RDEV_EXPDEV(n)	expdev(n)
Packit 6f02de
 *
Packit 6f02de
 *    to use the expdev() function to expand device numbers.  If
Packit 6f02de
 *    no RDEV_EXPDEV macro is defined, it defaults to:
Packit 6f02de
 *
Packit 6f02de
 *	#define RDEV_EXPDEV(n)	(n)
Packit 6f02de
 *
Packit 6f02de
 * 4. Define HASBLKDEV to request that information on S_IFBLK devices be
Packit 6f02de
 *    recorded in BDevtp[].
Packit 6f02de
 *
Packit 6f02de
 *    Define NOWARNBLKDEV to suppress the issuance of a warning when no
Packit 6f02de
 *    block devices are found.
Packit 6f02de
 *
Packit 6f02de
 * 5. Define RDEV_STATFN to be a stat function other than stat() or lstat()
Packit 6f02de
 *    -- e.g.,
Packit 6f02de
 *
Packit 6f02de
 *	#define	RDEV_STATFN	private_stat
Packit 6f02de
 *
Packit 6f02de
 * 6. Define HAS_STD_CLONE to request that clone device information be stored
Packit 6f02de
 *    in standard clone structures (defined in lsof.h and addressed via
Packit 6f02de
 *    Clone).  If HAS_STD_CLONE is defined, these must also be defined:
Packit 6f02de
 *
Packit 6f02de
 *	a.  Define CLONEMAJ to be the name of the constant or
Packit 6f02de
 *	    variable that defines the clone major device -- e.g.,
Packit 6f02de
 *
Packit 6f02de
 *		#define CLONEMAJ CloneMaj
Packit 6f02de
 *
Packit 6f02de
 *	b.  Define HAVECLONEMAJ to be the name of the variable that
Packit 6f02de
 *	    contains the status of the clone major device -- e.g.,
Packit 6f02de
 *
Packit 6f02de
 *		#define HAVECLONEMAJ HaveCloneMaj
Packit 6f02de
 *
Packit 6f02de
 *    Define HAS_STD_CLONE to be 1 if readdev() is expected to build the
Packit 6f02de
 *    clone table, the clone table is cached (if HASDCACHE is defined), and
Packit 6f02de
 *    there is a function to clear the cache table when the device table must
Packit 6f02de
 *    be reloaded.  (See dvch.c for naming the clone cache build and clear
Packit 6f02de
 *    functions.)
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
Packit 6f02de
# if	!defined(RDEV_EXPDEV)
Packit 6f02de
#define	RDEV_EXPDEV(n)		(n)
Packit 6f02de
# endif	/* !defined(RDEV_EXPDEV) */
Packit 6f02de
Packit 6f02de
# if	!defined(RDEV_STATFN)
Packit 6f02de
#  if	defined(USE_STAT)
Packit 6f02de
#define	RDEV_STATFN	stat
Packit 6f02de
#  else	/* !defined(USE_STAT) */
Packit 6f02de
#define	RDEV_STATFN	lstat
Packit 6f02de
#  endif	/* defined(USE_STAT) */
Packit 6f02de
# endif	/* !defined(RDEV_STATFN) */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * readdev() - read device names, modes and types
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
readdev(skip)
Packit 6f02de
	int skip;			/* skip device cache read if 1 */
Packit 6f02de
{
Packit 6f02de
Packit 6f02de
# if	defined(HAS_STD_CLONE) && HAS_STD_CLONE==1
Packit 6f02de
	struct clone *c;
Packit 6f02de
# endif	/* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
Packit 6f02de
Packit 6f02de
# if	defined(HASDCACHE)
Packit 6f02de
	int dcrd;
Packit 6f02de
# endif	/* defined(HASDCACHE) */
Packit 6f02de
Packit 6f02de
	DIR *dfp;
Packit 6f02de
	int dnamlen;
Packit 6f02de
	struct DIRTYPE *dp;
Packit 6f02de
	char *fp = (char *)NULL;
Packit 6f02de
	int i = 0;
Packit 6f02de
Packit 6f02de
# if	defined(HASBLKDEV)
Packit 6f02de
	int j = 0;
Packit 6f02de
# endif	/* defined(HASBLKDEV) */
Packit 6f02de
Packit 6f02de
	char *path = (char *)NULL;
Packit 6f02de
	MALLOC_S pl;
Packit 6f02de
	struct stat sb;
Packit 6f02de
Packit 6f02de
	if (Sdev)
Packit 6f02de
	    return;
Packit 6f02de
Packit 6f02de
# if	defined(HASDCACHE)
Packit 6f02de
/*
Packit 6f02de
 * Read device cache, as directed.
Packit 6f02de
 */
Packit 6f02de
	if (!skip) {
Packit 6f02de
	    if (DCstate == 2 || DCstate == 3) {
Packit 6f02de
		if ((dcrd = read_dcache()) == 0)
Packit 6f02de
		    return;
Packit 6f02de
	    }
Packit 6f02de
	} else
Packit 6f02de
	    dcrd = 1;
Packit 6f02de
# endif	/* defined(HASDCACHE) */
Packit 6f02de
Packit 6f02de
	Dstkn = Dstkx = 0;
Packit 6f02de
	Dstk = (char **)NULL;
Packit 6f02de
	(void) stkdir("/dev");
Packit 6f02de
/*
Packit 6f02de
 * Unstack the next /dev or /dev/<subdirectory> directory.
Packit 6f02de
 */
Packit 6f02de
	while (--Dstkx >= 0) {
Packit 6f02de
	    if (!(dfp = OpenDir(Dstk[Dstkx]))) {
Packit 6f02de
Packit 6f02de
# if	defined(WARNDEVACCESS)
Packit 6f02de
		if (!Fwarn) {
Packit 6f02de
		    (void) fprintf(stderr, "%s: WARNING: can't open: ", Pn);
Packit 6f02de
		    safestrprt(Dstk[Dstkx], stderr, 1);
Packit 6f02de
		}
Packit 6f02de
# endif	/* defined(WARNDEVACCESS) */
Packit 6f02de
Packit 6f02de
		(void) free((FREE_P *)Dstk[Dstkx]);
Packit 6f02de
		Dstk[Dstkx] = (char *)NULL;
Packit 6f02de
		continue;
Packit 6f02de
	    }
Packit 6f02de
	    if (path) {
Packit 6f02de
		(void) free((FREE_P *)path);
Packit 6f02de
		path = (char *)NULL;
Packit 6f02de
	    }
Packit 6f02de
	    if (!(path = mkstrcat(Dstk[Dstkx], -1, "/", 1, (char *)NULL, -1,
Packit 6f02de
				  &pl)))
Packit 6f02de
	    {
Packit 6f02de
		(void) fprintf(stderr, "%s: no space for: ", Pn);
Packit 6f02de
		safestrprt(Dstk[Dstkx], stderr, 1);
Packit 6f02de
		Exit(1);
Packit 6f02de
	    }
Packit 6f02de
	    (void) free((FREE_P *)Dstk[Dstkx]);
Packit 6f02de
	    Dstk[Dstkx] = (char *)NULL;
Packit 6f02de
	/*
Packit 6f02de
	 * Scan the directory.
Packit 6f02de
	 */
Packit 6f02de
	    for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) {
Packit 6f02de
		if (dp->d_ino == 0 || dp->d_name[0] == '.')
Packit 6f02de
		    continue;
Packit 6f02de
	    /*
Packit 6f02de
	     * Form the full path name and get its status.
Packit 6f02de
	     */
Packit 6f02de
Packit 6f02de
# if	defined(HASDNAMLEN)
Packit 6f02de
		dnamlen = (int)dp->d_namlen;
Packit 6f02de
# else	/* !defined(HASDNAMLEN) */
Packit 6f02de
		dnamlen = (int)strlen(dp->d_name);
Packit 6f02de
# endif	/* defined(HASDNAMLEN) */
Packit 6f02de
Packit 6f02de
		if (fp) {
Packit 6f02de
		    (void) free((FREE_P *)fp);
Packit 6f02de
		    fp = (char *)NULL;
Packit 6f02de
		}
Packit 6f02de
		if (!(fp = mkstrcat(path, pl, dp->d_name, dnamlen,
Packit 6f02de
				    (char *)NULL, -1, (MALLOC_S *)NULL)))
Packit 6f02de
		{
Packit 6f02de
		    (void) fprintf(stderr, "%s: no space for: ", Pn);
Packit 6f02de
		    safestrprt(path, stderr, 0);
Packit 6f02de
		    safestrprtn(dp->d_name, dnamlen, stderr, 1);
Packit 6f02de
		    Exit(1);
Packit 6f02de
		}
Packit 6f02de
		if (RDEV_STATFN(fp, &sb) != 0) {
Packit 6f02de
		    if (errno == ENOENT)	/* a sym link to nowhere? */
Packit 6f02de
			continue;
Packit 6f02de
Packit 6f02de
# if	defined(WARNDEVACCESS)
Packit 6f02de
		    if (!Fwarn) {
Packit 6f02de
			int errno_save = errno;
Packit 6f02de
Packit 6f02de
			(void) fprintf(stderr, "%s: can't stat ", Pn);
Packit 6f02de
			safestrprt(fp, stderr, 0);
Packit 6f02de
			(void) fprintf(stderr, ": %s\n", strerror(errno_save));
Packit 6f02de
		    }
Packit 6f02de
# endif	/* defined(WARNDEVACCESS) */
Packit 6f02de
Packit 6f02de
		    continue;
Packit 6f02de
		}
Packit 6f02de
	    /*
Packit 6f02de
	     * If it's a subdirectory, stack its name for later
Packit 6f02de
	     * processing.
Packit 6f02de
	     */
Packit 6f02de
		if ((sb.st_mode & S_IFMT) == S_IFDIR) {
Packit 6f02de
		    (void) stkdir(fp);
Packit 6f02de
		    continue;
Packit 6f02de
		}
Packit 6f02de
		if ((sb.st_mode & S_IFMT) == S_IFCHR) {
Packit 6f02de
Packit 6f02de
		/*
Packit 6f02de
		 * Save character device information in Devtp[].
Packit 6f02de
		 */
Packit 6f02de
		    if (i >= Ndev) {
Packit 6f02de
			Ndev += DEVINCR;
Packit 6f02de
			if (!Devtp)
Packit 6f02de
			    Devtp = (struct l_dev *)malloc(
Packit 6f02de
				    (MALLOC_S)(sizeof(struct l_dev)*Ndev));
Packit 6f02de
			else
Packit 6f02de
			    Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp,
Packit 6f02de
				    (MALLOC_S)(sizeof(struct l_dev)*Ndev));
Packit 6f02de
			if (!Devtp) {
Packit 6f02de
			    (void) fprintf(stderr,
Packit 6f02de
				"%s: no space for character device\n", Pn);
Packit 6f02de
			    Exit(1);
Packit 6f02de
			}
Packit 6f02de
		    }
Packit 6f02de
		    Devtp[i].rdev = RDEV_EXPDEV(sb.st_rdev);
Packit 6f02de
		    Devtp[i].inode = (INODETYPE)sb.st_ino;
Packit 6f02de
		    if (!(Devtp[i].name = mkstrcpy(fp, (MALLOC_S *)NULL))) {
Packit 6f02de
			(void) fprintf(stderr,
Packit 6f02de
			    "%s: no space for device name: ", Pn);
Packit 6f02de
			safestrprt(fp, stderr, 1);
Packit 6f02de
			Exit(1);
Packit 6f02de
		    }
Packit 6f02de
		    Devtp[i].v = 0;
Packit 6f02de
Packit 6f02de
# if	defined(HAS_STD_CLONE) && HAS_STD_CLONE==1
Packit 6f02de
		    if (HAVECLONEMAJ && GET_MAJ_DEV(Devtp[i].rdev) == CLONEMAJ)
Packit 6f02de
		    {
Packit 6f02de
Packit 6f02de
		    /*
Packit 6f02de
		     * Record clone device information.
Packit 6f02de
		     */
Packit 6f02de
			if (!(c = (struct clone *)malloc(sizeof(struct clone))))
Packit 6f02de
			{
Packit 6f02de
			    (void) fprintf(stderr,
Packit 6f02de
				"%s: no space for clone device: ", Pn);
Packit 6f02de
			    safestrprt(fp, stderr, 1);
Packit 6f02de
			    Exit(1);
Packit 6f02de
			}
Packit 6f02de
			c->dx = i;
Packit 6f02de
			c->next = Clone;
Packit 6f02de
			Clone = c;
Packit 6f02de
		    }
Packit 6f02de
# endif	/* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
Packit 6f02de
Packit 6f02de
		    i++;
Packit 6f02de
		}
Packit 6f02de
Packit 6f02de
# if	defined(HASBLKDEV)
Packit 6f02de
		if ((sb.st_mode & S_IFMT) == S_IFBLK) {
Packit 6f02de
Packit 6f02de
		/*
Packit 6f02de
		 * Save block device information in BDevtp[].
Packit 6f02de
		 */
Packit 6f02de
		    if (j >= BNdev) {
Packit 6f02de
			BNdev += DEVINCR;
Packit 6f02de
			if (!BDevtp)
Packit 6f02de
			    BDevtp = (struct l_dev *)malloc(
Packit 6f02de
				     (MALLOC_S)(sizeof(struct l_dev)*BNdev));
Packit 6f02de
			else
Packit 6f02de
			    BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp,
Packit 6f02de
				     (MALLOC_S)(sizeof(struct l_dev)*BNdev));
Packit 6f02de
			if (!BDevtp) {
Packit 6f02de
			    (void) fprintf(stderr,
Packit 6f02de
				"%s: no space for block device\n", Pn);
Packit 6f02de
			    Exit(1);
Packit 6f02de
			}
Packit 6f02de
		    }
Packit 6f02de
		    BDevtp[j].name = fp;
Packit 6f02de
		    fp = (char *)NULL;
Packit 6f02de
		    BDevtp[j].inode = (INODETYPE)sb.st_ino;
Packit 6f02de
		    BDevtp[j].rdev = RDEV_EXPDEV(sb.st_rdev);
Packit 6f02de
		    BDevtp[j].v = 0;
Packit 6f02de
		    j++;
Packit 6f02de
		}
Packit 6f02de
# endif	/* defined(HASBLKDEV) */
Packit 6f02de
Packit 6f02de
	    }
Packit 6f02de
	    (void) CloseDir(dfp);
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * Free any allocated space.
Packit 6f02de
 */
Packit 6f02de
	if (!Dstk) {
Packit 6f02de
	    (void) free((FREE_P *)Dstk);
Packit 6f02de
	    Dstk = (char **)NULL;
Packit 6f02de
	}
Packit 6f02de
	if (fp)
Packit 6f02de
	    (void) free((FREE_P *)fp);
Packit 6f02de
	if (path)
Packit 6f02de
	    (void) free((FREE_P *)path);
Packit 6f02de
Packit 6f02de
# if	defined(HASBLKDEV)
Packit 6f02de
/*
Packit 6f02de
 * Reduce the BDevtp[] (optional) and Devtp[] tables to their minimum
Packit 6f02de
 * sizes; allocate and build sort pointer lists; and sort the tables by
Packit 6f02de
 * device number.
Packit 6f02de
 */
Packit 6f02de
	if (BNdev) {
Packit 6f02de
	    if (BNdev > j) {
Packit 6f02de
		BNdev = j;
Packit 6f02de
		BDevtp = (struct l_dev *)realloc((MALLOC_P *)BDevtp,
Packit 6f02de
			 (MALLOC_S)(sizeof(struct l_dev) * BNdev));
Packit 6f02de
	    }
Packit 6f02de
	    if (!(BSdev = (struct l_dev **)malloc(
Packit 6f02de
			  (MALLOC_S)(sizeof(struct l_dev *) * BNdev))))
Packit 6f02de
	    {
Packit 6f02de
		(void) fprintf(stderr,
Packit 6f02de
		    "%s: no space for block device sort pointers\n", Pn);
Packit 6f02de
		Exit(1);
Packit 6f02de
	    }
Packit 6f02de
	    for (j = 0; j < BNdev; j++) {
Packit 6f02de
		BSdev[j] = &BDevtp[j];
Packit 6f02de
	    }
Packit 6f02de
	    (void) qsort((QSORT_P *)BSdev, (size_t)BNdev,
Packit 6f02de
		(size_t)sizeof(struct l_dev *), compdev);
Packit 6f02de
	    BNdev = rmdupdev(&BSdev, BNdev, "block");
Packit 6f02de
	}
Packit 6f02de
	
Packit 6f02de
#  if	!defined(NOWARNBLKDEV)
Packit 6f02de
	else {
Packit 6f02de
	    if (!Fwarn)
Packit 6f02de
		(void) fprintf(stderr,
Packit 6f02de
		    "%s: WARNING: no block devices found\n", Pn);
Packit 6f02de
	}
Packit 6f02de
#  endif	/* !defined(NOWARNBLKDEV) */
Packit 6f02de
# endif	/* defined(HASBLKDEV) */
Packit 6f02de
Packit 6f02de
	if (Ndev) {
Packit 6f02de
	    if (Ndev > i) {
Packit 6f02de
		Ndev = i;
Packit 6f02de
		Devtp = (struct l_dev *)realloc((MALLOC_P *)Devtp,
Packit 6f02de
			(MALLOC_S)(sizeof(struct l_dev) * Ndev));
Packit 6f02de
	    }
Packit 6f02de
	    if (!(Sdev = (struct l_dev **)malloc(
Packit 6f02de
			 (MALLOC_S)(sizeof(struct l_dev *) * Ndev))))
Packit 6f02de
	    {
Packit 6f02de
		(void) fprintf(stderr,
Packit 6f02de
		    "%s: no space for character device sort pointers\n", Pn);
Packit 6f02de
		Exit(1);
Packit 6f02de
	    }
Packit 6f02de
	    for (i = 0; i < Ndev; i++) {
Packit 6f02de
		Sdev[i] = &Devtp[i];
Packit 6f02de
	    }
Packit 6f02de
	    (void) qsort((QSORT_P *)Sdev, (size_t)Ndev,
Packit 6f02de
		(size_t)sizeof(struct l_dev *), compdev);
Packit 6f02de
	    Ndev = rmdupdev(&Sdev, Ndev, "char");
Packit 6f02de
	} else {
Packit 6f02de
	    (void) fprintf(stderr, "%s: no character devices found\n", Pn);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
Packit 6f02de
# if	defined(HASDCACHE)
Packit 6f02de
/*
Packit 6f02de
 * Write device cache file, as required.
Packit 6f02de
 */
Packit 6f02de
	if (DCstate == 1 || (DCstate == 3 && dcrd))
Packit 6f02de
	    write_dcache();
Packit 6f02de
# endif	/* defined(HASDCACHE) */
Packit 6f02de
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
# if	defined(HASDCACHE)
Packit 6f02de
/*
Packit 6f02de
 * rereaddev() - reread device names, modes and types
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
rereaddev()
Packit 6f02de
{
Packit 6f02de
	(void) clr_devtab();
Packit 6f02de
Packit 6f02de
# if	defined(DCACHE_CLR)
Packit 6f02de
	(void) DCACHE_CLR();
Packit 6f02de
# endif	/* defined(DCACHE_CLR) */
Packit 6f02de
Packit 6f02de
	readdev(1);
Packit 6f02de
	DCunsafe = 0;
Packit 6f02de
}
Packit 6f02de
#endif	/* defined(HASDCACHE) */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * rmdupdev() - remove duplicate (major/minor/inode) devices
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
static int
Packit 6f02de
rmdupdev(dp, n, nm)
Packit 6f02de
	struct l_dev ***dp;	/* device table pointers address */
Packit 6f02de
	int n;			/* number of pointers */
Packit 6f02de
	char *nm;		/* device table name for error message */
Packit 6f02de
{
Packit 6f02de
Packit 6f02de
# if	defined(HAS_STD_CLONE) && HAS_STD_CLONE==1
Packit 6f02de
	struct clone *c, *cp;
Packit 6f02de
# endif	/* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
Packit 6f02de
Packit 6f02de
	int i, j, k;
Packit 6f02de
	struct l_dev **p;
Packit 6f02de
Packit 6f02de
	for (i = j = 0, p = *dp; i < n ;) {
Packit 6f02de
	    for (k = i + 1; k < n; k++) {
Packit 6f02de
		if (p[i]->rdev != p[k]->rdev || p[i]->inode != p[k]->inode)
Packit 6f02de
		    break;
Packit 6f02de
Packit 6f02de
# if	defined(HAS_STD_CLONE) && HAS_STD_CLONE==1
Packit 6f02de
	    /*
Packit 6f02de
	     * See if we're deleting a duplicate clone device.  If so,
Packit 6f02de
	     * delete its clone table entry.
Packit 6f02de
	     */
Packit 6f02de
		for (c = Clone, cp = (struct clone *)NULL;
Packit 6f02de
		     c;
Packit 6f02de
		     cp = c, c = c->next)
Packit 6f02de
		{
Packit 6f02de
		    if (&Devtp[c->dx] != p[k])
Packit 6f02de
			continue;
Packit 6f02de
		    if (!cp)
Packit 6f02de
			Clone = c->next;
Packit 6f02de
		    else
Packit 6f02de
			cp->next = c->next;
Packit 6f02de
		    (void) free((FREE_P *)c);
Packit 6f02de
		    break;
Packit 6f02de
		}
Packit 6f02de
# endif	/* defined(HAS_STD_CLONE) && HAS_STD_CLONE==1 */
Packit 6f02de
Packit 6f02de
	    }
Packit 6f02de
	    if (i != j)
Packit 6f02de
		p[j] = p[i];
Packit 6f02de
	    j++;
Packit 6f02de
	    i = k;
Packit 6f02de
	}
Packit 6f02de
	if (n == j)
Packit 6f02de
	    return(n);
Packit 6f02de
	if (!(*dp = (struct l_dev **)realloc((MALLOC_P *)*dp,
Packit 6f02de
		    (MALLOC_S)(j * sizeof(struct l_dev *)))))
Packit 6f02de
	{
Packit 6f02de
	    (void) fprintf(stderr, "%s: can't realloc %s device pointers\n",
Packit 6f02de
		Pn, nm);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
	return(j);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
# if	defined(HASDCACHE)
Packit 6f02de
/*
Packit 6f02de
 * vfy_dev() - verify a device table entry (usually when DCunsafe == 1)
Packit 6f02de
 *
Packit 6f02de
 * Note: rereads entire device table when an entry can't be verified.
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
vfy_dev(dp)
Packit 6f02de
	struct l_dev *dp;		/* device table pointer */
Packit 6f02de
{
Packit 6f02de
	struct stat sb;
Packit 6f02de
Packit 6f02de
	if (!DCunsafe || dp->v)
Packit 6f02de
	    return(1);
Packit 6f02de
	if (RDEV_STATFN(dp->name, &sb) != 0
Packit 6f02de
	||  dp->rdev != RDEV_EXPDEV(sb.st_rdev)
Packit 6f02de
	||  dp->inode != sb.st_ino) {
Packit 6f02de
	   (void) rereaddev();
Packit 6f02de
	   return(0);
Packit 6f02de
	}
Packit 6f02de
	dp->v = 1;
Packit 6f02de
	return(1);
Packit 6f02de
}
Packit 6f02de
# endif	/* defined(HASDCACHE) */
Packit 6f02de
#else	/* !defined(USE_LIB_READDEV) */
Packit 6f02de
char rdev_d1[] = "d"; char *rdev_d2 = rdev_d1;
Packit 6f02de
#endif	/* defined(USE_LIB_READDEV) */