|
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) */
|