1 /* $NetBSD: dir.c,v 1.23 2009/10/19 18:41:07 bouyer Exp $ */
4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Copyright (c) 1997 Manuel Bouyer.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
45 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
48 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
53 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 #include <sys/cdefs.h>
59 static char sccsid
[] = "@(#)dir.c 8.5 (Berkeley) 12/8/94";
61 __RCSID("$NetBSD: dir.c,v 1.23 2009/10/19 18:41:07 bouyer Exp $");
65 #include <sys/param.h>
67 #include <ufs/ufs/dir.h>
68 #include <ufs/ext2fs/ext2fs_dinode.h>
69 #include <ufs/ext2fs/ext2fs_dir.h>
70 #include <ufs/ext2fs/ext2fs.h>
72 #include <ufs/ufs/dinode.h> /* for IFMT & friends */
83 const char *lfname
= "lost+found";
85 struct ext2fs_dirtemplate emptydir
= {
87 .dot_reclen
= DIRBLKSIZ
,
89 struct ext2fs_dirtemplate dirhead
= {
93 .dot_type
= EXT2_FT_DIR
,
96 .dotdot_reclen
= DIRBLKSIZ
- 12,
98 .dotdot_type
= EXT2_FT_DIR
,
103 static int expanddir(struct ext2fs_dinode
*, char *);
104 static void freedir(ino_t
, ino_t
);
105 static struct ext2fs_direct
*fsck_readdir(struct inodesc
*);
106 static struct bufarea
*getdirblk(daddr_t
, long);
107 static int lftempname(char *, ino_t
);
108 static int mkentry(struct inodesc
*);
109 static int chgino(struct inodesc
*);
112 * Propagate connected state through the tree.
117 struct inoinfo
**inpp
, *inp
, *pinp
;
118 struct inoinfo
**inpend
;
121 * Create a list of children for each directory.
123 inpend
= &inpsort
[inplast
];
124 for (inpp
= inpsort
; inpp
< inpend
; inpp
++) {
126 if (inp
->i_parent
== 0 ||
127 inp
->i_number
== EXT2_ROOTINO
)
129 pinp
= getinoinfo(inp
->i_parent
);
130 inp
->i_parentp
= pinp
;
131 inp
->i_sibling
= pinp
->i_child
;
134 inp
= getinoinfo(EXT2_ROOTINO
);
136 statemap
[inp
->i_number
] = DFOUND
;
138 statemap
[inp
->i_child
->i_number
] == DSTATE
)
140 else if (inp
->i_sibling
)
141 inp
= inp
->i_sibling
;
143 inp
= inp
->i_parentp
;
148 * Scan each entry in a directory block.
151 dirscan(struct inodesc
*idesc
)
153 struct ext2fs_direct
*dp
;
159 if ((dbuf
= malloc(sblock
.e2fs_bsize
)) == NULL
)
160 err(8, "Can't allocate directory block");
162 if (idesc
->id_type
!= DATA
)
163 errexit("wrong type to dirscan %d", idesc
->id_type
);
164 if (idesc
->id_entryno
== 0 &&
165 (idesc
->id_filesize
& (sblock
.e2fs_bsize
- 1)) != 0)
166 idesc
->id_filesize
= roundup(idesc
->id_filesize
, sblock
.e2fs_bsize
);
167 blksiz
= idesc
->id_numfrags
* sblock
.e2fs_bsize
;
168 if (chkrange(idesc
->id_blkno
, idesc
->id_numfrags
)) {
169 idesc
->id_filesize
-= blksiz
;
174 for (dp
= fsck_readdir(idesc
); dp
!= NULL
; dp
= fsck_readdir(idesc
)) {
175 dsize
= fs2h16(dp
->e2d_reclen
);
176 memcpy(dbuf
, dp
, (size_t)dsize
);
177 idesc
->id_dirp
= (struct ext2fs_direct
*)dbuf
;
178 if ((n
= (*idesc
->id_func
)(idesc
)) & ALTERED
) {
179 bp
= getdirblk(idesc
->id_blkno
, blksiz
);
180 memcpy(bp
->b_un
.b_buf
+ idesc
->id_loc
- dsize
, dbuf
,
191 return (idesc
->id_filesize
> 0 ? KEEPON
: STOP
);
195 * get next entry in a directory.
197 static struct ext2fs_direct
*
198 fsck_readdir(struct inodesc
*idesc
)
200 struct ext2fs_direct
*dp
, *ndp
;
202 long size
, blksiz
, fix
, dploc
;
204 blksiz
= idesc
->id_numfrags
* sblock
.e2fs_bsize
;
205 bp
= getdirblk(idesc
->id_blkno
, blksiz
);
206 if (idesc
->id_loc
% sblock
.e2fs_bsize
== 0 && idesc
->id_filesize
> 0 &&
207 idesc
->id_loc
< blksiz
) {
208 dp
= (struct ext2fs_direct
*)(bp
->b_un
.b_buf
+ idesc
->id_loc
);
209 if (dircheck(idesc
, dp
))
211 if (idesc
->id_fix
== IGNORE
)
213 fix
= dofix(idesc
, "DIRECTORY CORRUPTED");
214 bp
= getdirblk(idesc
->id_blkno
, blksiz
);
215 dp
= (struct ext2fs_direct
*)(bp
->b_un
.b_buf
+ idesc
->id_loc
);
216 dp
->e2d_reclen
= h2fs16(sblock
.e2fs_bsize
);
220 dp
->e2d_name
[0] = '\0';
223 idesc
->id_loc
+= sblock
.e2fs_bsize
;
224 idesc
->id_filesize
-= sblock
.e2fs_bsize
;
228 if (idesc
->id_filesize
<= 0 || idesc
->id_loc
>= blksiz
)
230 dploc
= idesc
->id_loc
;
231 dp
= (struct ext2fs_direct
*)(bp
->b_un
.b_buf
+ dploc
);
232 idesc
->id_loc
+= fs2h16(dp
->e2d_reclen
);
233 idesc
->id_filesize
-= fs2h16(dp
->e2d_reclen
);
234 if ((idesc
->id_loc
% sblock
.e2fs_bsize
) == 0)
236 ndp
= (struct ext2fs_direct
*)(bp
->b_un
.b_buf
+ idesc
->id_loc
);
237 if (idesc
->id_loc
< blksiz
&& idesc
->id_filesize
> 0 &&
238 dircheck(idesc
, ndp
) == 0) {
239 size
= sblock
.e2fs_bsize
- (idesc
->id_loc
% sblock
.e2fs_bsize
);
240 idesc
->id_loc
+= size
;
241 idesc
->id_filesize
-= size
;
242 if (idesc
->id_fix
== IGNORE
)
244 fix
= dofix(idesc
, "DIRECTORY CORRUPTED");
245 bp
= getdirblk(idesc
->id_blkno
, blksiz
);
246 dp
= (struct ext2fs_direct
*)(bp
->b_un
.b_buf
+ dploc
);
247 dp
->e2d_reclen
= h2fs16(fs2h16(dp
->e2d_reclen
) + size
);
255 * Verify that a directory entry is valid.
256 * This is a superset of the checks made in the kernel.
259 dircheck(struct inodesc
*idesc
, struct ext2fs_direct
*dp
)
264 u_int16_t reclen
= fs2h16(dp
->e2d_reclen
);
266 spaceleft
= sblock
.e2fs_bsize
- (idesc
->id_loc
% sblock
.e2fs_bsize
);
267 if (fs2h32(dp
->e2d_ino
) > maxino
||
269 reclen
> spaceleft
||
272 if (dp
->e2d_ino
== 0)
274 if (sblock
.e2fs
.e2fs_rev
< E2FS_REV1
||
275 (sblock
.e2fs
.e2fs_features_incompat
& EXT2F_INCOMPAT_FTYPE
) == 0)
276 if (dp
->e2d_type
!= 0)
278 size
= EXT2FS_DIRSIZ(dp
->e2d_namlen
);
280 idesc
->id_filesize
< size
/* ||
281 dp->e2d_namlen > EXT2FS_MAXNAMLEN */)
283 for (cp
= dp
->e2d_name
, size
= 0; size
< dp
->e2d_namlen
; size
++)
284 if (*cp
== '\0' || (*cp
++ == '/'))
290 direrror(ino_t ino
, const char *errmesg
)
293 fileerror(ino
, ino
, errmesg
);
297 fileerror(ino_t cwd
, ino_t ino
, const char *errmesg
)
299 struct ext2fs_dinode
*dp
;
300 char pathbuf
[MAXPATHLEN
+ 1];
302 pwarn("%s ", errmesg
);
305 getpathname(pathbuf
, sizeof(pathbuf
), cwd
, ino
);
306 if ((ino
< EXT2_FIRSTINO
&& ino
!= EXT2_ROOTINO
) || ino
> maxino
) {
307 pfatal("NAME=%s\n", pathbuf
);
313 (fs2h16(dp
->e2di_mode
) & IFMT
) == IFDIR
? "DIR" : "FILE", pathbuf
);
315 pfatal("NAME=%s\n", pathbuf
);
319 adjust(struct inodesc
*idesc
, short lcnt
)
321 struct ext2fs_dinode
*dp
;
323 dp
= ginode(idesc
->id_number
);
324 if (fs2h16(dp
->e2di_nlink
) == lcnt
) {
325 if (linkup(idesc
->id_number
, (ino_t
)0) == 0)
326 clri(idesc
, "UNREF", 0);
328 pwarn("LINK COUNT %s", (lfdir
== idesc
->id_number
) ? lfname
:
329 ((fs2h16(dp
->e2di_mode
) & IFMT
) == IFDIR
? "DIR" : "FILE"));
330 pinode(idesc
->id_number
);
331 printf(" COUNT %d SHOULD BE %d",
332 fs2h16(dp
->e2di_nlink
), fs2h16(dp
->e2di_nlink
) - lcnt
);
336 pfatal("LINK COUNT INCREASING");
338 printf(" (ADJUSTED)\n");
340 if (preen
|| reply("ADJUST") == 1) {
341 dp
->e2di_nlink
= h2fs16(fs2h16(dp
->e2di_nlink
) - lcnt
);
348 mkentry(struct inodesc
*idesc
)
350 struct ext2fs_direct
*dirp
= idesc
->id_dirp
;
351 struct ext2fs_direct newent
;
354 newent
.e2d_type
= 0; /* XXX gcc */
355 newent
.e2d_namlen
= strlen(idesc
->id_name
);
356 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
357 (sblock
.e2fs
.e2fs_features_incompat
& EXT2F_INCOMPAT_FTYPE
))
358 newent
.e2d_type
= inot2ext2dt(typemap
[idesc
->id_parent
]);
359 newlen
= EXT2FS_DIRSIZ(newent
.e2d_namlen
);
360 if (dirp
->e2d_ino
!= 0)
361 oldlen
= EXT2FS_DIRSIZ(dirp
->e2d_namlen
);
364 if (fs2h16(dirp
->e2d_reclen
) - oldlen
< newlen
)
366 newent
.e2d_reclen
= h2fs16(fs2h16(dirp
->e2d_reclen
) - oldlen
);
367 dirp
->e2d_reclen
= h2fs16(oldlen
);
368 dirp
= (struct ext2fs_direct
*)(((char *)dirp
) + oldlen
);
369 dirp
->e2d_ino
= h2fs32(idesc
->id_parent
); /* ino to be entered is in id_parent */
370 dirp
->e2d_reclen
= newent
.e2d_reclen
;
371 dirp
->e2d_namlen
= newent
.e2d_namlen
;
372 dirp
->e2d_type
= newent
.e2d_type
;
373 memcpy(dirp
->e2d_name
, idesc
->id_name
, (size_t)(dirp
->e2d_namlen
));
374 return (ALTERED
|STOP
);
378 chgino(struct inodesc
*idesc
)
380 struct ext2fs_direct
*dirp
= idesc
->id_dirp
;
381 u_int16_t namlen
= dirp
->e2d_namlen
;
383 if (strlen(idesc
->id_name
) != namlen
||
384 strncmp(dirp
->e2d_name
, idesc
->id_name
, (int)namlen
))
386 dirp
->e2d_ino
= h2fs32(idesc
->id_parent
);
387 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
388 (sblock
.e2fs
.e2fs_features_incompat
& EXT2F_INCOMPAT_FTYPE
))
389 dirp
->e2d_type
= inot2ext2dt(typemap
[idesc
->id_parent
]);
392 return (ALTERED
|STOP
);
396 linkup(ino_t orphan
, ino_t parentdir
)
398 struct ext2fs_dinode
*dp
;
401 struct inodesc idesc
;
402 char tempname
[BUFSIZ
];
404 memset(&idesc
, 0, sizeof(struct inodesc
));
406 lostdir
= (fs2h16(dp
->e2di_mode
) & IFMT
) == IFDIR
;
407 pwarn("UNREF %s ", lostdir
? "DIR" : "FILE");
409 if (preen
&& inosize(dp
) == 0)
412 printf(" (RECONNECTED)\n");
414 if (reply("RECONNECT") == 0)
417 dp
= ginode(EXT2_ROOTINO
);
418 idesc
.id_name
= lfname
;
419 idesc
.id_type
= DATA
;
420 idesc
.id_func
= findino
;
421 idesc
.id_number
= EXT2_ROOTINO
;
422 if ((ckinode(dp
, &idesc
) & FOUND
) != 0) {
423 lfdir
= idesc
.id_parent
;
425 pwarn("NO lost+found DIRECTORY");
426 if (preen
|| reply("CREATE")) {
427 lfdir
= allocdir(EXT2_ROOTINO
, (ino_t
)0, lfmode
);
429 if (makeentry(EXT2_ROOTINO
, lfdir
, lfname
) != 0) {
431 printf(" (CREATED)\n");
433 freedir(lfdir
, EXT2_ROOTINO
);
442 pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY");
448 if ((fs2h16(dp
->e2di_mode
) & IFMT
) != IFDIR
) {
449 pfatal("lost+found IS NOT A DIRECTORY");
450 if (reply("REALLOCATE") == 0)
453 if ((lfdir
= allocdir(EXT2_ROOTINO
, (ino_t
)0, lfmode
)) == 0) {
454 pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
457 if ((changeino(EXT2_ROOTINO
, lfname
, lfdir
) & ALTERED
) == 0) {
458 pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
462 idesc
.id_type
= ADDR
;
463 idesc
.id_func
= pass4check
;
464 idesc
.id_number
= oldlfdir
;
465 adjust(&idesc
, lncntp
[oldlfdir
] + 1);
466 lncntp
[oldlfdir
] = 0;
469 if (statemap
[lfdir
] != DFOUND
) {
470 pfatal("SORRY. NO lost+found DIRECTORY\n\n");
473 (void)lftempname(tempname
, orphan
);
474 if (makeentry(lfdir
, orphan
, tempname
) == 0) {
475 pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
481 if ((changeino(orphan
, "..", lfdir
) & ALTERED
) == 0 &&
482 parentdir
!= (ino_t
)-1)
483 (void)makeentry(orphan
, lfdir
, "..");
485 dp
->e2di_nlink
= h2fs16(fs2h16(dp
->e2di_nlink
) +1);
488 pwarn("DIR I=%llu CONNECTED. ", (unsigned long long)orphan
);
489 if (parentdir
!= (ino_t
)-1)
490 printf("PARENT WAS I=%llu\n",
491 (unsigned long long)parentdir
);
499 * fix an entry in a directory.
502 changeino(ino_t dir
, const char *name
, ino_t newnum
)
504 struct inodesc idesc
;
506 memset(&idesc
, 0, sizeof(struct inodesc
));
507 idesc
.id_type
= DATA
;
508 idesc
.id_func
= chgino
;
509 idesc
.id_number
= dir
;
510 idesc
.id_fix
= DONTKNOW
;
511 idesc
.id_name
= name
;
512 idesc
.id_parent
= newnum
; /* new value for name */
513 return (ckinode(ginode(dir
), &idesc
));
517 * make an entry in a directory
520 makeentry(ino_t parent
, ino_t ino
, const char *name
)
522 struct ext2fs_dinode
*dp
;
523 struct inodesc idesc
;
524 char pathbuf
[MAXPATHLEN
+ 1];
526 if ((parent
< EXT2_FIRSTINO
&& parent
!= EXT2_ROOTINO
)
527 || parent
>= maxino
||
528 (ino
< EXT2_FIRSTINO
&& ino
< EXT2_ROOTINO
) || ino
>= maxino
)
530 memset(&idesc
, 0, sizeof(struct inodesc
));
531 idesc
.id_type
= DATA
;
532 idesc
.id_func
= mkentry
;
533 idesc
.id_number
= parent
;
534 idesc
.id_parent
= ino
; /* this is the inode to enter */
535 idesc
.id_fix
= DONTKNOW
;
536 idesc
.id_name
= name
;
538 if (inosize(dp
) % sblock
.e2fs_bsize
) {
539 inossize(dp
, roundup(inosize(dp
), sblock
.e2fs_bsize
));
542 if ((ckinode(dp
, &idesc
) & ALTERED
) != 0)
544 getpathname(pathbuf
, sizeof(pathbuf
), parent
, parent
);
546 if (expanddir(dp
, pathbuf
) == 0)
548 return (ckinode(dp
, &idesc
) & ALTERED
);
552 * Attempt to expand the size of a directory
555 expanddir(struct ext2fs_dinode
*dp
, char *name
)
557 daddr_t lastbn
, newblk
;
561 lastbn
= lblkno(&sblock
, inosize(dp
));
562 if (lastbn
>= NDADDR
- 1 || fs2h32(dp
->e2di_blocks
[lastbn
]) == 0 ||
566 if ((newblk
= allocblk()) == 0) {
569 dp
->e2di_blocks
[lastbn
+ 1] = dp
->e2di_blocks
[lastbn
];
570 dp
->e2di_blocks
[lastbn
] = h2fs32(newblk
);
571 inossize(dp
, inosize(dp
) + sblock
.e2fs_bsize
);
572 dp
->e2di_nblock
= h2fs32(fs2h32(dp
->e2di_nblock
) + 1);
573 bp
= getdirblk(fs2h32(dp
->e2di_blocks
[lastbn
+ 1]),
577 if ((firstblk
= malloc(sblock
.e2fs_bsize
)) == NULL
)
578 err(8, "cannot allocate first block");
579 memcpy(firstblk
, bp
->b_un
.b_buf
, sblock
.e2fs_bsize
);
580 bp
= getdirblk(newblk
, sblock
.e2fs_bsize
);
585 memcpy(bp
->b_un
.b_buf
, firstblk
, sblock
.e2fs_bsize
);
588 bp
= getdirblk(fs2h32(dp
->e2di_blocks
[lastbn
+ 1]),
592 emptydir
.dot_reclen
= h2fs16(sblock
.e2fs_bsize
);
593 memcpy(bp
->b_un
.b_buf
, &emptydir
, sizeof emptydir
);
594 pwarn("NO SPACE LEFT IN %s", name
);
596 printf(" (EXPANDED)\n");
597 else if (reply("EXPAND") == 0)
603 dp
->e2di_blocks
[lastbn
] = dp
->e2di_blocks
[lastbn
+ 1];
604 dp
->e2di_blocks
[lastbn
+ 1] = 0;
605 inossize(dp
, inosize(dp
) - sblock
.e2fs_bsize
);
606 dp
->e2di_nblock
= h2fs32(fs2h32(dp
->e2di_nblock
) - 1);
612 * allocate a new directory
615 allocdir(ino_t parent
, ino_t request
, int mode
)
618 struct ext2fs_dinode
*dp
;
620 struct ext2fs_dirtemplate
*dirp
;
622 ino
= allocino(request
, IFDIR
|mode
);
623 dirhead
.dot_reclen
= h2fs16(12); /* XXX */
624 dirhead
.dotdot_reclen
= h2fs16(sblock
.e2fs_bsize
- 12); /* XXX */
625 dirhead
.dot_namlen
= 1;
626 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
627 (sblock
.e2fs
.e2fs_features_incompat
& EXT2F_INCOMPAT_FTYPE
))
628 dirhead
.dot_type
= EXT2_FT_DIR
;
630 dirhead
.dot_type
= 0;
631 dirhead
.dotdot_namlen
= 2;
632 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
633 (sblock
.e2fs
.e2fs_features_incompat
& EXT2F_INCOMPAT_FTYPE
))
634 dirhead
.dotdot_type
= EXT2_FT_DIR
;
636 dirhead
.dotdot_type
= 0;
638 dirp
->dot_ino
= h2fs32(ino
);
639 dirp
->dotdot_ino
= h2fs32(parent
);
641 bp
= getdirblk(fs2h32(dp
->e2di_blocks
[0]), sblock
.e2fs_bsize
);
646 memcpy(bp
->b_un
.b_buf
, dirp
, sizeof(struct ext2fs_dirtemplate
));
648 dp
->e2di_nlink
= h2fs16(2);
650 if (ino
== EXT2_ROOTINO
) {
651 lncntp
[ino
] = fs2h16(dp
->e2di_nlink
);
655 if (statemap
[parent
] != DSTATE
&& statemap
[parent
] != DFOUND
) {
660 statemap
[ino
] = statemap
[parent
];
661 if (statemap
[ino
] == DSTATE
) {
662 lncntp
[ino
] = fs2h16(dp
->e2di_nlink
);
666 dp
->e2di_nlink
= h2fs16(fs2h16(dp
->e2di_nlink
) + 1);
672 * free a directory inode
675 freedir(ino_t ino
, ino_t parent
)
677 struct ext2fs_dinode
*dp
;
681 dp
->e2di_nlink
= h2fs16(fs2h16(dp
->e2di_nlink
) - 1);
688 * generate a temporary name for the lost+found directory.
691 lftempname(char *bufp
, ino_t ino
)
698 for (in
= maxino
; in
> 0; in
/= 10)
704 *--cp
= (in
% 10) + '0';
712 * Get a directory block.
713 * Insure that it is held until another is requested.
715 static struct bufarea
*
716 getdirblk(daddr_t blkno
, long size
)
720 pdirbp
->b_flags
&= ~B_INUSE
;
721 pdirbp
= getdatablk(blkno
, size
);