* Copyright (c) 1980, 1986 The Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)inode.c 5.18 (Berkeley) %G%";
register struct inodesc
*idesc
;
long ret
, n
, ndb
, offset
;
if (idesc
->id_fix
!= IGNORE
)
idesc
->id_fix
= DONTKNOW
;
idesc
->id_filesize
= dp
->di_size
;
if ((dp
->di_mode
& IFMT
) == IFBLK
|| (dp
->di_mode
& IFMT
) == IFCHR
)
ndb
= howmany(dino
.di_size
, sblock
.fs_bsize
);
for (ap
= &dino
.di_db
[0]; ap
< &dino
.di_db
[NDADDR
]; ap
++) {
if (--ndb
== 0 && (offset
= blkoff(&sblock
, dino
.di_size
)) != 0)
numfrags(&sblock
, fragroundup(&sblock
, offset
));
idesc
->id_numfrags
= sblock
.fs_frag
;
if (idesc
->id_type
== ADDR
)
ret
= (*idesc
->id_func
)(idesc
);
idesc
->id_numfrags
= sblock
.fs_frag
;
for (ap
= &dino
.di_ib
[0], n
= 1; n
<= NIADDR
; ap
++, n
++) {
dino
.di_size
- sblock
.fs_bsize
* NDADDR
);
iblock(idesc
, ilevel
, isize
)
int i
, n
, (*func
)(), nif
, sizepb
;
register struct bufarea
*bp
;
extern int dirscan(), pass1check();
if (idesc
->id_type
== ADDR
) {
if (((n
= (*func
)(idesc
)) & KEEPON
) == 0)
if (chkrange(idesc
->id_blkno
, idesc
->id_numfrags
))
bp
= getdatablk(idesc
->id_blkno
, sblock
.fs_bsize
);
for (sizepb
= sblock
.fs_bsize
, i
= 0; i
< ilevel
; i
++)
sizepb
*= NINDIR(&sblock
);
nif
= isize
/ sizepb
+ 1;
if (nif
> NINDIR(&sblock
))
if (idesc
->id_func
== pass1check
&& nif
< NINDIR(&sblock
)) {
aplim
= &bp
->b_un
.b_indir
[NINDIR(&sblock
)];
for (ap
= &bp
->b_un
.b_indir
[nif
]; ap
< aplim
; ap
++) {
(void)sprintf(buf
, "PARTIALLY TRUNCATED INODE I=%lu",
aplim
= &bp
->b_un
.b_indir
[nif
];
for (ap
= bp
->b_un
.b_indir
, i
= 1; ap
< aplim
; ap
++, i
++) {
n
= iblock(idesc
, ilevel
, isize
- i
* sizepb
);
* Check that a block in a legal block number.
* Return 0 if in range, 1 if out of range.
if ((unsigned)(blk
+ cnt
) > maxfsblock
)
if (blk
< cgdmin(&sblock
, c
)) {
if ((blk
+ cnt
) > cgsblock(&sblock
, c
)) {
printf("blk %ld < cgdmin %ld;",
blk
, cgdmin(&sblock
, c
));
printf(" blk + cnt %ld > cgsbase %ld\n",
blk
+ cnt
, cgsblock(&sblock
, c
));
if ((blk
+ cnt
) > cgbase(&sblock
, c
+1)) {
printf("blk %ld >= cgdmin %ld;",
blk
, cgdmin(&sblock
, c
));
printf(" blk + cnt %ld > sblock.fs_fpg %ld\n",
* General purpose interface for reading inodes.
if (inumber
< ROOTINO
|| inumber
> maxino
)
errexit("bad inode number %d to ginode\n", inumber
);
inumber
< startinum
|| inumber
>= startinum
+ INOPB(&sblock
)) {
iblk
= itod(&sblock
, inumber
);
pbp
->b_flags
&= ~B_INUSE
;
pbp
= getdatablk(iblk
, sblock
.fs_bsize
);
startinum
= (inumber
/ INOPB(&sblock
)) * INOPB(&sblock
);
return (&pbp
->b_un
.b_dinode
[inumber
% INOPB(&sblock
)]);
* Special purpose version of ginode used to optimize first pass
* over all the inodes in numerical order.
long readcnt
, readpercg
, fullcnt
, inobufsize
, partialcnt
, partialsize
;
static struct dinode
*dp
;
if (inumber
!= nextino
++ || inumber
> maxino
)
errexit("bad inode number %d to nextinode\n", inumber
);
if (inumber
>= lastinum
) {
dblk
= fsbtodb(&sblock
, itod(&sblock
, lastinum
));
if (readcnt
% readpercg
== 0) {
(void)bread(fsreadfd
, (char *)inodebuf
, dblk
, size
); /* ??? */
inobufsize
= blkroundup(&sblock
, INOBUFSIZE
);
fullcnt
= inobufsize
/ sizeof(struct dinode
);
readpercg
= sblock
.fs_ipg
/ fullcnt
;
partialcnt
= sblock
.fs_ipg
% fullcnt
;
partialsize
= partialcnt
* sizeof(struct dinode
);
partialsize
= inobufsize
;
(inodebuf
= (struct dinode
*)malloc((unsigned)inobufsize
)) == NULL
)
errexit("Cannot allocate space for inode buffer\n");
while (nextino
< ROOTINO
)
(void)getnextinode(nextino
);
* Routines to maintain information about directory inodes.
* This is built during the first pass and used during the
* second and third passes.
* Enter inodes into the cache.
register struct dinode
*dp
;
register struct inoinfo
*inp
;
blks
= howmany(dp
->di_size
, sblock
.fs_bsize
);
malloc(sizeof(*inp
) + (blks
- 1) * sizeof(daddr_t
));
inpp
= &inphead
[inumber
% numdirs
];
inp
->i_parent
= (ino_t
)0;
inp
->i_dotdot
= (ino_t
)0;
inp
->i_isize
= dp
->di_size
;
inp
->i_numblks
= blks
* sizeof(daddr_t
);
bcopy((char *)&dp
->di_db
[0], (char *)&inp
->i_blks
[0],
if (inplast
== listmax
) {
inpsort
= (struct inoinfo
**)realloc((char *)inpsort
,
(unsigned)listmax
* sizeof(struct inoinfo
*));
errexit("cannot increase directory list");
inpsort
[inplast
++] = inp
;
* Look up an inode cache structure.
register struct inoinfo
*inp
;
for (inp
= inphead
[inumber
% numdirs
]; inp
; inp
= inp
->i_nexthash
) {
if (inp
->i_number
!= inumber
)
errexit("cannot find inode %d\n", inumber
);
return ((struct inoinfo
*)0);
* Clean up all the inode cache structure.
register struct inoinfo
**inpp
;
for (inpp
= &inpsort
[inplast
- 1]; inpp
>= inpsort
; inpp
--)
inphead
= inpsort
= NULL
;
register struct inodesc
*idesc
;
register struct dinode
*dp
;
dp
= ginode(idesc
->id_number
);
(dp
->di_mode
& IFMT
) == IFDIR
? "DIR" : "FILE");
pinode(idesc
->id_number
);
if (preen
|| reply("CLEAR") == 1) {
(void)ckinode(dp
, idesc
);
statemap
[idesc
->id_number
] = USTATE
;
register struct direct
*dirp
= idesc
->id_dirp
;
if (dirp
->d_ino
!= idesc
->id_parent
)
bcopy(dirp
->d_name
, idesc
->id_name
, (size_t)dirp
->d_namlen
+ 1);
register struct direct
*dirp
= idesc
->id_dirp
;
if (strcmp(dirp
->d_name
, idesc
->id_name
) == 0 &&
dirp
->d_ino
>= ROOTINO
&& dirp
->d_ino
<= maxino
) {
idesc
->id_parent
= dirp
->d_ino
;
register struct dinode
*dp
;
if (ino
< ROOTINO
|| ino
> maxino
)
if ((pw
= getpwuid((int)dp
->di_uid
)) != 0)
printf("%s ", pw
->pw_name
);
printf("%u ", (unsigned)dp
->di_uid
);
printf("MODE=%o\n", dp
->di_mode
);
printf("SIZE=%lu ", dp
->di_size
);
p
= ctime(&dp
->di_mtime
);
printf("MTIME=%12.12s %4.4s ", &p
[4], &p
[20]);
pfatal("%ld %s I=%lu", blk
, type
, ino
);
errexit("BAD STATE %d TO BLKERR", statemap
[ino
]);
* allocate an unused inode
register struct dinode
*dp
;
else if (statemap
[request
] != USTATE
)
for (ino
= request
; ino
< maxino
; ino
++)
if (statemap
[ino
] == USTATE
)
dp
->di_db
[0] = allocblk((long)1);
(void)time(&dp
->di_atime
);
dp
->di_mtime
= dp
->di_ctime
= dp
->di_atime
;
dp
->di_size
= sblock
.fs_fsize
;
dp
->di_blocks
= btodb(sblock
.fs_fsize
);
bzero((char *)&idesc
, sizeof(struct inodesc
));
idesc
.id_func
= pass4check
;
(void)ckinode(dp
, &idesc
);