Files
Arquivotheca.SunOS-4.1.4/usr.etc/ncheck.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

448 lines
8.2 KiB
C

#ifndef lint
static char sccsid[] = "@(#)ncheck.c 1.1 94/10/31 SMI"; /* from UCB 5.4 1/9/86 */
#endif
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
All rights reserved.\n";
#endif not lint
/*
* ncheck -- obtain file names from reading filesystem
*/
#define MAXNINDIR (MAXBSIZE / sizeof (daddr_t))
#include <sys/param.h>
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/label.h>
#include <sys/audit.h>
#include <sys/file.h>
#include <ufs/inode.h>
#include <ufs/fs.h>
#include <ufs/fsdir.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
union {
struct fs sblk;
char xxx[SBSIZE]; /* because fs is variable length */
} real_fs;
#define sblock real_fs.sblk
struct dinode itab[MAXBSIZE/sizeof(struct dinode)];
struct dinode *gip;
struct ilist {
struct ilist *next;
ino_t ino;
u_short mode;
short uid, gid;
} *ilist = NULL;
struct htab
{
ino_t h_ino;
ino_t h_pino;
char *h_name;
} *htab;
long hsize;
struct dirstuff {
int loc;
struct dinode *ip;
char dbuf[MAXBSIZE];
};
int aflg;
int sflg;
int mflg;
int fi;
ino_t ino;
int nhent;
int nerror;
static void bread(), check(), add_to_ilist();
static daddr_t bmap();
static char *alloc();
static struct htab *lookup();
static struct direct *dreaddir();
extern long atol();
extern char *malloc(), *calloc();
main(argc, argv)
int argc;
char *argv[];
{
audit_args(AU_MINPRIV, argc, argv);
while (--argc) {
argv++;
if (**argv != '-') {
check(*argv);
continue;
}
switch ((*argv)[1]) {
case 'a':
aflg++;
continue;
case 'i':
while (argv[1] != 0 && isdigit(*argv[1])) {
add_to_ilist((ino_t)atol(argv[1]));
argv++;
argc--;
}
continue;
case 'm':
mflg++;
continue;
case 's':
sflg++;
continue;
default:
(void) fprintf(stderr,
"ncheck: bad flag %c\n", (*argv)[1]);
nerror++;
}
}
return (nerror);
}
static void
check(file)
char *file;
{
register int i, j, c;
register struct ilist *il;
register struct htab *h;
fi = open(file, O_RDONLY, 0);
if (fi < 0) {
(void) fprintf(stderr, "ncheck: cannot open %s\n", file);
nerror++;
return;
}
nhent = 0;
(void) printf("%s:\n", file);
sync();
bread(SBLOCK, (char *)&sblock, SBSIZE);
if (sblock.fs_magic != FS_MAGIC) {
(void) printf("%s: not a file system\n", file);
nerror++;
return;
}
hsize = sblock.fs_ipg * sblock.fs_ncg - sblock.fs_cstotal.cs_nifree + 1;
htab = (struct htab *)calloc((unsigned)hsize, sizeof (struct htab));
if (htab == 0) {
(void) printf("not enough memory to allocate tables\n");
nerror++;
return;
}
ino = 0;
for (c = 0; c < sblock.fs_ncg; c++) {
for (i = 0;
i < sblock.fs_ipg / INOPF(&sblock);
i += sblock.fs_frag) {
bread(fsbtodb(&sblock, cgimin(&sblock, c) + i),
(char *)itab, sblock.fs_bsize);
for (j = 0; j < INOPB(&sblock); j++) {
if (itab[j].di_mode != 0)
pass1(&itab[j]);
ino++;
}
}
}
ino = 0;
for (c = 0; c < sblock.fs_ncg; c++) {
for (i = 0;
i < sblock.fs_ipg / INOPF(&sblock);
i += sblock.fs_frag) {
bread(fsbtodb(&sblock, cgimin(&sblock, c) + i),
(char *)itab, sblock.fs_bsize);
for (j = 0; j < INOPB(&sblock); j++) {
if (itab[j].di_mode != 0)
pass2(&itab[j]);
ino++;
}
}
}
ino = 0;
for (c = 0; c < sblock.fs_ncg; c++) {
for (i = 0;
i < sblock.fs_ipg / INOPF(&sblock);
i += sblock.fs_frag) {
bread(fsbtodb(&sblock, cgimin(&sblock, c) + i),
(char *)itab, sblock.fs_bsize);
for (j = 0; j < INOPB(&sblock); j++) {
if (itab[j].di_mode != 0)
pass3(&itab[j]);
ino++;
}
}
}
(void) close(fi);
for (h = htab; h != htab + hsize; h++) {
if (h->h_name != NULL)
free(h->h_name);
}
free((char *)htab);
while (ilist != NULL) {
il = ilist->next;
free((char *)ilist);
ilist = il;
}
}
pass1(ip)
register struct dinode *ip;
{
register struct ilist *il;
register int fmt = ip->di_mode & IFMT;
if (mflg) {
for (il = ilist; il != NULL; il = il->next)
if (ino == il->ino) {
il->mode = ip->di_mode;
il->uid = ip->di_uid;
il->gid = ip->di_gid;
}
}
if (sflg) {
if (fmt == IFBLK || fmt == IFCHR ||
fmt != IFDIR && (ip->di_mode & (ISUID|ISGID))) {
add_to_ilist(ino);
ilist->mode = ip->di_mode;
ilist->uid = ip->di_uid;
ilist->gid = ip->di_gid;
}
}
if (fmt == IFDIR)
(void) lookup(ino, 1);
}
pass2(ip)
register struct dinode *ip;
{
register struct direct *dp;
struct dirstuff dirp;
struct htab *hp;
if ((ip->di_mode&IFMT) != IFDIR)
return;
dirp.loc = 0;
dirp.ip = ip;
gip = ip;
for (dp = dreaddir(&dirp); dp != NULL; dp = dreaddir(&dirp)) {
if (dp->d_ino == 0)
continue;
hp = lookup(dp->d_ino, 0);
if (hp == 0)
continue;
if (dotname(dp))
continue;
hp->h_pino = ino;
hp->h_name = alloc((u_int)(strlen(dp->d_name) + 1));
(void) strcpy(hp->h_name, dp->d_name);
}
}
pass3(ip)
register struct dinode *ip;
{
register struct direct *dp;
struct dirstuff dirp;
register struct ilist *il;
if ((ip->di_mode & IFMT) != IFDIR)
return;
dirp.loc = 0;
dirp.ip = ip;
gip = ip;
for (dp = dreaddir(&dirp); dp != NULL; dp = dreaddir(&dirp)) {
if (aflg == 0 && dotname(dp))
continue;
if (sflg == 0 && ilist == NULL)
goto pr;
for (il = ilist; il != NULL; il = il->next)
if (il->ino == dp->d_ino)
break;
if (il == NULL)
continue;
if (mflg)
(void) printf("mode %-6o uid %-5d gid %-5d ino ",
il->mode, il->uid, il->gid);
pr:
(void) printf("%-5u\t", dp->d_ino);
pname(ino, 0);
(void) printf("/%s", dp->d_name);
if (lookup(dp->d_ino, 0))
(void) printf("/.");
(void) printf("\n");
}
}
/*
* get next entry in a directory.
*/
static struct direct *
dreaddir(dirp)
register struct dirstuff *dirp;
{
register struct direct *dp;
daddr_t lbn, d;
for (;;) {
if (dirp->loc >= dirp->ip->di_size)
return NULL;
if (blkoff(&sblock, dirp->loc) == 0) {
lbn = lblkno(&sblock, dirp->loc);
d = bmap(lbn);
if (d == 0)
return NULL;
bread(fsbtodb(&sblock, d), dirp->dbuf,
(int)dblksize(&sblock, dirp->ip, (int)lbn));
}
dp = (struct direct *)
(dirp->dbuf + blkoff(&sblock, dirp->loc));
dirp->loc += dp->d_reclen;
if (dp->d_ino == 0)
continue;
return (dp);
}
}
dotname(dp)
struct direct *dp;
{
register char *p = dp->d_name;
return (p[0] == '.' && (p[1] == 0 || (p[1] == '.' && p[2] == 0)));
}
pname(i, lev)
ino_t i;
int lev;
{
register struct htab *hp;
if (i == ROOTINO)
return;
if ((hp = lookup(i, 0)) == 0) {
(void) printf("???");
return;
}
if (lev > 10) {
(void) printf("...");
return;
}
pname(hp->h_pino, ++lev);
(void) printf("/%s", hp->h_name);
}
static struct htab *
lookup(i, ef)
ino_t i;
int ef;
{
register struct htab *hp;
for (hp = &htab[i % hsize]; hp->h_ino;) {
if (hp->h_ino == i)
return (hp);
if (++hp >= &htab[hsize])
hp = htab;
}
if (ef == 0)
return (0);
if (++nhent >= hsize) {
(void) fprintf(stderr,
"ncheck: hsize of %d is too small\n", hsize);
exit(1);
}
hp->h_ino = i;
return (hp);
}
static void
bread(bno, buf, cnt)
daddr_t bno;
char *buf;
int cnt;
{
int got;
if (lseek(fi, (long)(bno * DEV_BSIZE), L_SET) == (long) -1) {
(void) fprintf(stderr,
"ncheck: lseek error %d\n", bno * DEV_BSIZE);
bzero(buf, cnt);
return;
}
got = read(fi, buf, cnt);
if (got != cnt) {
(void) fprintf(stderr,
"ncheck: read error %d (wanted %d got %d)\n",
bno, cnt, got);
if (got == -1)
perror("ncheck");
bzero(buf, cnt);
}
}
static daddr_t
bmap(i)
daddr_t i;
{
daddr_t ibuf[MAXNINDIR];
if (i < NDADDR)
return (gip->di_db[i]);
i -= NDADDR;
if (i > NINDIR(&sblock)) {
(void) fprintf(stderr, "ncheck: %u - huge directory\n", ino);
return ((daddr_t)0);
}
bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof (ibuf));
return (ibuf[i]);
}
static void
add_to_ilist(inum)
ino_t inum;
{
struct ilist *il;
il = (struct ilist *)alloc(sizeof (struct ilist));
il->ino = inum;
il->next = ilist;
ilist = il;
}
static char *
alloc(n)
unsigned n;
{
char *p;
p = malloc(n);
if (p == NULL) {
perror("ncheck");
exit(1);
}
return p;
}