static char version
[] = "@(#)dir.c 3.5 (Berkeley) %G%";
#define MINDIRSIZE (sizeof (struct dirtemplate))
char *endpathname
= &pathname
[BUFSIZ
- 2];
char *lfname
= "lost+found";
struct dirtemplate emptydir
= { 0, DIRBLKSIZ
};
descend(parentino
, inumber
)
struct inodesc
*parentino
;
bzero((char *)&curino
, sizeof(struct inodesc
));
if (statemap
[inumber
] != DSTATE
)
errexit("BAD INODE %d TO DESCEND", statemap
[inumber
]);
statemap
[inumber
] = DFOUND
;
direrr(inumber
, "ZERO LENGTH DIRECTORY");
if (reply("REMOVE") == 1)
statemap
[inumber
] = DCLEAR
;
if (dp
->di_size
< MINDIRSIZE
) {
direrr(inumber
, "DIRECTORY TOO SHORT");
dp
->di_size
= MINDIRSIZE
;
curino
.id_func
= parentino
->id_func
;
curino
.id_parent
= parentino
->id_number
;
curino
.id_number
= inumber
;
curino
.id_filesize
= dp
->di_size
;
(void)ckinode(dp
, &curino
);
register struct inodesc
*idesc
;
if (idesc
->id_type
!= DATA
)
errexit("wrong type to dirscan %d\n", idesc
->id_type
);
blksiz
= idesc
->id_numfrags
* sblock
.fs_fsize
;
if (outrange(idesc
->id_blkno
, idesc
->id_numfrags
)) {
idesc
->id_filesize
-= blksiz
;
for (dp
= fsck_readdir(idesc
); dp
!= NULL
; dp
= fsck_readdir(idesc
)) {
bcopy((char *)dp
, dbuf
, dsize
);
idesc
->id_dirp
= (DIRECT
*)dbuf
;
if ((n
= (*idesc
->id_func
)(idesc
)) & ALTERED
) {
if (getblk(&fileblk
, idesc
->id_blkno
, blksiz
) != NULL
) {
bcopy(dbuf
, (char *)dp
, dsize
);
return (idesc
->id_filesize
> 0 ? KEEPON
: STOP
);
* get next entry in a directory.
register struct inodesc
*idesc
;
register DIRECT
*dp
, *ndp
;
blksiz
= idesc
->id_numfrags
* sblock
.fs_fsize
;
if (getblk(&fileblk
, idesc
->id_blkno
, blksiz
) == NULL
) {
idesc
->id_filesize
-= blksiz
- idesc
->id_loc
;
if (idesc
->id_loc
% DIRBLKSIZ
== 0 && idesc
->id_filesize
> 0 &&
idesc
->id_loc
< blksiz
) {
dp
= (DIRECT
*)(dirblk
.b_buf
+ idesc
->id_loc
);
idesc
->id_loc
+= DIRBLKSIZ
;
idesc
->id_filesize
-= DIRBLKSIZ
;
dp
->d_reclen
= DIRBLKSIZ
;
if (dofix(idesc
, "DIRECTORY CORRUPTED"))
if (idesc
->id_filesize
<= 0 || idesc
->id_loc
>= blksiz
)
dp
= (DIRECT
*)(dirblk
.b_buf
+ idesc
->id_loc
);
idesc
->id_loc
+= dp
->d_reclen
;
idesc
->id_filesize
-= dp
->d_reclen
;
if ((idesc
->id_loc
% DIRBLKSIZ
) == 0)
ndp
= (DIRECT
*)(dirblk
.b_buf
+ idesc
->id_loc
);
if (idesc
->id_loc
< blksiz
&& idesc
->id_filesize
> 0 &&
dircheck(idesc
, ndp
) == 0) {
size
= DIRBLKSIZ
- (idesc
->id_loc
% DIRBLKSIZ
);
idesc
->id_filesize
-= size
;
if (dofix(idesc
, "DIRECTORY CORRUPTED"))
* Verify that a directory entry is valid.
* This is a superset of the checks made in the kernel.
spaceleft
= DIRBLKSIZ
- (idesc
->id_loc
% DIRBLKSIZ
);
dp
->d_reclen
<= spaceleft
&&
(dp
->d_reclen
& 0x3) == 0 &&
idesc
->id_filesize
>= size
&&
dp
->d_namlen
<= MAXNAMLEN
) {
for (cp
= dp
->d_name
, size
= 0; size
< dp
->d_namlen
; size
++)
if (*cp
== 0 || (*cp
++ & 0200))
if (ino
< ROOTINO
|| ino
> imax
) {
pfatal("NAME=%s\n", pathname
);
pfatal("%s=%s\n", DIRCT(dp
) ? "DIR" : "FILE", pathname
);
pfatal("NAME=%s\n", pathname
);
register struct inodesc
*idesc
;
dp
= ginode(idesc
->id_number
);
if (dp
->di_nlink
== lcnt
) {
if (linkup(idesc
->id_number
, (ino_t
)0) == 0)
pwarn("LINK COUNT %s", (lfdir
== idesc
->id_number
) ? lfname
:
(DIRCT(dp
) ? "DIR" : "FILE"));
pinode(idesc
->id_number
);
printf(" COUNT %d SHOULD BE %d",
dp
->di_nlink
, dp
->di_nlink
-lcnt
);
pfatal("LINK COUNT INCREASING");
if (preen
|| reply("ADJUST") == 1) {
register DIRECT
*dirp
= idesc
->id_dirp
;
newlen
= DIRSIZ(&newent
);
if (dirp
->d_reclen
- oldlen
< newlen
)
newent
.d_reclen
= dirp
->d_reclen
- oldlen
;
dirp
= (struct direct
*)(((char *)dirp
) + oldlen
);
dirp
->d_ino
= idesc
->id_parent
; /* ino to be entered is in id_parent */
dirp
->d_reclen
= newent
.d_reclen
;
dirp
->d_namlen
= lftempname(dirp
->d_name
, idesc
->id_parent
);
register DIRECT
*dirp
= idesc
->id_dirp
;
if (dirp
->d_name
[0] == '.' && dirp
->d_name
[1] == '.' &&
bzero((char *)&idesc
, sizeof(struct inodesc
));
pwarn("UNREF %s ", lostdir
? "DIR" : "FILE");
if (preen
&& dp
->di_size
== 0)
printf(" (RECONNECTED)\n");
if (reply("RECONNECT") == 0)
idesc
.id_number
= ROOTINO
;
idesc
.id_filesize
= dp
->di_size
;
(void)ckinode(dp
, &idesc
);
if (lfdir
< ROOTINO
|| lfdir
> imax
)
pfatal("SORRY. NO lost+found DIRECTORY");
if (!DIRCT(dp
) || statemap
[lfdir
] != DFOUND
) {
pfatal("SORRY. NO lost+found DIRECTORY");
if (dp
->di_size
% DIRBLKSIZ
) {
dp
->di_size
= roundup(dp
->di_size
, DIRBLKSIZ
);
bcopy(lfname
, pathp
, len
+ 1);
idesc
.id_filesize
= dp
->di_size
;
idesc
.id_parent
= orphan
; /* this is the inode to enter */
if (makeentry(dp
, &idesc
) == 0) {
pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
pathp
+= lftempname(pathp
, orphan
);
idesc
.id_number
= orphan
;
idesc
.id_filesize
= dp
->di_size
;
(void)ckinode(dp
, &idesc
);
pwarn("DIR I=%u CONNECTED. ", orphan
);
printf("PARENT WAS I=%u\n", pdir
);
* make an entry in a directory
if ((ckinode(dp
, idesc
) & ALTERED
) != 0)
idesc
->id_filesize
= dp
->di_size
;
return (ckinode(dp
, idesc
) & ALTERED
);
* Attempt to expand the size of a directory
char *cp
, firstblk
[DIRBLKSIZ
];
lastbn
= lblkno(&sblock
, dp
->di_size
);
if (lastbn
>= NDADDR
- 1)
if ((newblk
= allocblk(sblock
.fs_frag
)) == 0)
dp
->di_db
[lastbn
+ 1] = dp
->di_db
[lastbn
];
dp
->di_db
[lastbn
] = newblk
;
dp
->di_size
+= sblock
.fs_bsize
;
dp
->di_blocks
+= btodb(sblock
.fs_bsize
);
if (getblk(&fileblk
, dp
->di_db
[lastbn
+ 1],
dblksize(&sblock
, dp
, lastbn
+ 1)) == NULL
)
bcopy(dirblk
.b_buf
, firstblk
, DIRBLKSIZ
);
if (getblk(&fileblk
, newblk
, sblock
.fs_bsize
) == NULL
)
bcopy(firstblk
, dirblk
.b_buf
, DIRBLKSIZ
);
for (cp
= &dirblk
.b_buf
[DIRBLKSIZ
];
cp
< &dirblk
.b_buf
[sblock
.fs_bsize
];
bcopy((char *)&emptydir
, cp
, sizeof emptydir
);
if (getblk(&fileblk
, dp
->di_db
[lastbn
+ 1],
dblksize(&sblock
, dp
, lastbn
+ 1)) == NULL
)
bcopy((char *)&emptydir
, dirblk
.b_buf
, sizeof emptydir
);
pwarn("NO SPACE LEFT IN %s", pathname
);
else if (reply("EXPAND") == 0)
dp
->di_db
[lastbn
] = dp
->di_db
[lastbn
+ 1];
dp
->di_db
[lastbn
+ 1] = 0;
dp
->di_size
-= sblock
.fs_bsize
;
dp
->di_blocks
-= btodb(sblock
.fs_bsize
);
freeblk(newblk
, sblock
.fs_frag
);
* generate a temporary name for the lost+found directory.
for (in
= imax
; in
> 0; in
/= 10)