Deleted Added
sdiff udiff text old ( 15699 ) new ( 23675 )
full compact
1/*
2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 18 unchanged lines hidden (view full) ---

27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static const char sccsid[] = "@(#)dir.c 8.1 (Berkeley) 6/5/93";
36#endif /* not lint */
37
38#include <sys/param.h>
39#include <sys/time.h>
40#include <ufs/ufs/dinode.h>
41#include <ufs/ufs/dir.h>
42#include <ufs/ffs/fs.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include "fsck.h"
47
48char *lfname = "lost+found";
49int lfmode = 01777;
50struct dirtemplate emptydir = { 0, DIRBLKSIZ };
51struct dirtemplate dirhead = {
52 0, 12, DT_DIR, 1, ".",
53 0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
54};
55struct odirtemplate odirhead = {
56 0, 12, 1, ".",
57 0, DIRBLKSIZ - 12, 2, ".."
58};
59
60
61static int chgino __P((struct inodesc *idesc));
62static int dircheck __P((struct inodesc *idesc, struct direct *dp));
63static int expanddir __P((struct dinode *dp, char *name));
64static void freedir __P((ino_t ino, ino_t parent));
65static struct direct * fsck_readdir __P((struct inodesc *idesc));
66static struct bufarea * getdirblk __P((daddr_t blkno, long size));
67static int lftempname __P((char *bufp, ino_t ino));
68static int mkentry __P((struct inodesc *idesc));
69
70/*
71 * Propagate connected state through the tree.
72 */
73void
74propagate()
75{
76 register struct inoinfo **inpp, *inp;
77 struct inoinfo **inpend;

--- 24 unchanged lines hidden (view full) ---

102{
103 register struct direct *dp;
104 register struct bufarea *bp;
105 int dsize, n;
106 long blksiz;
107 char dbuf[DIRBLKSIZ];
108
109 if (idesc->id_type != DATA)
110 errexit("wrong type to dirscan %d\n", idesc->id_type);
111 if (idesc->id_entryno == 0 &&
112 (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0)
113 idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ);
114 blksiz = idesc->id_numfrags * sblock.fs_fsize;
115 if (chkrange(idesc->id_blkno, idesc->id_numfrags)) {
116 idesc->id_filesize -= blksiz;
117 return (SKIP);
118 }
119 idesc->id_loc = 0;
120 for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
121 dsize = dp->d_reclen;
122 bcopy((char *)dp, dbuf, (size_t)dsize);
123# if (BYTE_ORDER == LITTLE_ENDIAN)
124 if (!newinofmt) {
125 struct direct *tdp = (struct direct *)dbuf;
126 u_char tmp;
127
128 tmp = tdp->d_namlen;
129 tdp->d_namlen = tdp->d_type;
130 tdp->d_type = tmp;

--- 8 unchanged lines hidden (view full) ---

139
140 tdp = (struct direct *)dbuf;
141 tmp = tdp->d_namlen;
142 tdp->d_namlen = tdp->d_type;
143 tdp->d_type = tmp;
144 }
145# endif
146 bp = getdirblk(idesc->id_blkno, blksiz);
147 bcopy(dbuf, bp->b_un.b_buf + idesc->id_loc - dsize,
148 (size_t)dsize);
149 dirty(bp);
150 sbdirty();
151 }
152 if (n & STOP)
153 return (n);
154 }
155 return (idesc->id_filesize > 0 ? KEEPON : STOP);
156}
157
158/*
159 * get next entry in a directory.
160 */
161struct direct *
162fsck_readdir(idesc)
163 register struct inodesc *idesc;
164{
165 register struct direct *dp, *ndp;
166 register struct bufarea *bp;
167 long size, blksiz, fix, dploc;
168
169 blksiz = idesc->id_numfrags * sblock.fs_fsize;
170 bp = getdirblk(idesc->id_blkno, blksiz);
171 if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 &&
172 idesc->id_loc < blksiz) {
173 dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
174 if (dircheck(idesc, dp))
175 goto dpok;
176 fix = dofix(idesc, "DIRECTORY CORRUPTED");
177 bp = getdirblk(idesc->id_blkno, blksiz);
178 dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
179 dp->d_reclen = DIRBLKSIZ;
180 dp->d_ino = 0;
181 dp->d_type = 0;
182 dp->d_namlen = 0;
183 dp->d_name[0] = '\0';

--- 13 unchanged lines hidden (view full) ---

197 if ((idesc->id_loc % DIRBLKSIZ) == 0)
198 return (dp);
199 ndp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
200 if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
201 dircheck(idesc, ndp) == 0) {
202 size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
203 idesc->id_loc += size;
204 idesc->id_filesize -= size;
205 fix = dofix(idesc, "DIRECTORY CORRUPTED");
206 bp = getdirblk(idesc->id_blkno, blksiz);
207 dp = (struct direct *)(bp->b_un.b_buf + dploc);
208 dp->d_reclen += size;
209 if (fix)
210 dirty(bp);
211 }
212 return (dp);
213}
214
215/*
216 * Verify that a directory entry is valid.
217 * This is a superset of the checks made in the kernel.
218 */
219int
220dircheck(idesc, dp)
221 struct inodesc *idesc;
222 register struct direct *dp;
223{
224 register int size;
225 register char *cp;
226 u_char namlen, type;
227 int spaceleft;
228
229 size = DIRSIZ(!newinofmt, dp);
230 spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
231# if (BYTE_ORDER == LITTLE_ENDIAN)
232 if (!newinofmt) {
233 type = dp->d_namlen;
234 namlen = dp->d_type;
235 } else {
236 namlen = dp->d_namlen;
237 type = dp->d_type;
238 }
239# else
240 namlen = dp->d_namlen;
241 type = dp->d_type;
242# endif
243 if (dp->d_ino < maxino &&
244 dp->d_reclen != 0 &&
245 dp->d_reclen <= spaceleft &&
246 (dp->d_reclen & 0x3) == 0 &&
247 dp->d_reclen >= size &&
248 idesc->id_filesize >= size &&
249 namlen <= MAXNAMLEN &&
250 type <= 15) {
251 if (dp->d_ino == 0)
252 return (1);
253 for (cp = dp->d_name, size = 0; size < namlen; size++)
254 if (*cp == 0 || (*cp++ == '/'))
255 return (0);
256 if (*cp == 0)
257 return (1);
258 }
259 return (0);
260}
261
262void
263direrror(ino, errmesg)
264 ino_t ino;
265 char *errmesg;
266{
267

--- 22 unchanged lines hidden (view full) ---

290 (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf);
291 else
292 pfatal("NAME=%s\n", pathbuf);
293}
294
295void
296adjust(idesc, lcnt)
297 register struct inodesc *idesc;
298 short lcnt;
299{
300 register struct dinode *dp;
301
302 dp = ginode(idesc->id_number);
303 if (dp->di_nlink == lcnt) {
304 if (linkup(idesc->id_number, (ino_t)0) == 0)
305 clri(idesc, "UNREF", 0);
306 } else {

--- 11 unchanged lines hidden (view full) ---

318 }
319 if (preen || reply("ADJUST") == 1) {
320 dp->di_nlink -= lcnt;
321 inodirty();
322 }
323 }
324}
325
326int
327mkentry(idesc)
328 struct inodesc *idesc;
329{
330 register struct direct *dirp = idesc->id_dirp;
331 struct direct newent;
332 int newlen, oldlen;
333
334 newent.d_namlen = strlen(idesc->id_name);
335 newlen = DIRSIZ(0, &newent);
336 if (dirp->d_ino != 0)
337 oldlen = DIRSIZ(0, dirp);
338 else
339 oldlen = 0;
340 if (dirp->d_reclen - oldlen < newlen)
341 return (KEEPON);
342 newent.d_reclen = dirp->d_reclen - oldlen;
343 dirp->d_reclen = oldlen;
344 dirp = (struct direct *)(((char *)dirp) + oldlen);
345 dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */
346 if (newinofmt) {
347 dirp->d_type = typemap[idesc->id_parent];
348 dirp->d_namlen = newent.d_namlen;
349 } else {
350# if (BYTE_ORDER == LITTLE_ENDIAN)
351 dirp->d_type = newent.d_namlen;
352 dirp->d_namlen = 0;
353# else
354 dirp->d_type = 0;
355 dirp->d_namlen = newent.d_namlen;
356# endif
357 }
358 dirp->d_reclen = newent.d_reclen;
359 bcopy(idesc->id_name, dirp->d_name, (size_t)newent.d_namlen + 1);
360 return (ALTERED|STOP);
361}
362
363int
364chgino(idesc)
365 struct inodesc *idesc;
366{
367 register struct direct *dirp = idesc->id_dirp;
368
369 if (bcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1))
370 return (KEEPON);
371 dirp->d_ino = idesc->id_parent;
372 if (newinofmt)
373 dirp->d_type = typemap[idesc->id_parent];
374 else
375 dirp->d_type = 0;
376 return (ALTERED|STOP);
377}

--- 4 unchanged lines hidden (view full) ---

382 ino_t parentdir;
383{
384 register struct dinode *dp;
385 int lostdir;
386 ino_t oldlfdir;
387 struct inodesc idesc;
388 char tempname[BUFSIZ];
389
390 bzero((char *)&idesc, sizeof(struct inodesc));
391 dp = ginode(orphan);
392 lostdir = (dp->di_mode & IFMT) == IFDIR;
393 pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
394 pinode(orphan);
395 if (preen && dp->di_size == 0)
396 return (0);
397 if (preen)
398 printf(" (RECONNECTED)\n");

--- 97 unchanged lines hidden (view full) ---

496int
497changeino(dir, name, newnum)
498 ino_t dir;
499 char *name;
500 ino_t newnum;
501{
502 struct inodesc idesc;
503
504 bzero((char *)&idesc, sizeof(struct inodesc));
505 idesc.id_type = DATA;
506 idesc.id_func = chgino;
507 idesc.id_number = dir;
508 idesc.id_fix = DONTKNOW;
509 idesc.id_name = name;
510 idesc.id_parent = newnum; /* new value for name */
511 return (ckinode(ginode(dir), &idesc));
512}

--- 8 unchanged lines hidden (view full) ---

521{
522 struct dinode *dp;
523 struct inodesc idesc;
524 char pathbuf[MAXPATHLEN + 1];
525
526 if (parent < ROOTINO || parent >= maxino ||
527 ino < ROOTINO || ino >= maxino)
528 return (0);
529 bzero((char *)&idesc, sizeof(struct inodesc));
530 idesc.id_type = DATA;
531 idesc.id_func = mkentry;
532 idesc.id_number = parent;
533 idesc.id_parent = ino; /* this is the inode to enter */
534 idesc.id_fix = DONTKNOW;
535 idesc.id_name = name;
536 dp = ginode(parent);
537 if (dp->di_size % DIRBLKSIZ) {

--- 7 unchanged lines hidden (view full) ---

545 if (expanddir(dp, pathbuf) == 0)
546 return (0);
547 return (ckinode(dp, &idesc) & ALTERED);
548}
549
550/*
551 * Attempt to expand the size of a directory
552 */
553int
554expanddir(dp, name)
555 register struct dinode *dp;
556 char *name;
557{
558 daddr_t lastbn, newblk;
559 register struct bufarea *bp;
560 char *cp, firstblk[DIRBLKSIZ];
561
562 lastbn = lblkno(&sblock, dp->di_size);
563 if (lastbn >= NDADDR - 1 || dp->di_db[lastbn] == 0 || dp->di_size == 0)
564 return (0);
565 if ((newblk = allocblk(sblock.fs_frag)) == 0)
566 return (0);
567 dp->di_db[lastbn + 1] = dp->di_db[lastbn];
568 dp->di_db[lastbn] = newblk;
569 dp->di_size += sblock.fs_bsize;
570 dp->di_blocks += btodb(sblock.fs_bsize);
571 bp = getdirblk(dp->di_db[lastbn + 1],
572 (long)dblksize(&sblock, dp, lastbn + 1));
573 if (bp->b_errs)
574 goto bad;
575 bcopy(bp->b_un.b_buf, firstblk, DIRBLKSIZ);
576 bp = getdirblk(newblk, sblock.fs_bsize);
577 if (bp->b_errs)
578 goto bad;
579 bcopy(firstblk, bp->b_un.b_buf, DIRBLKSIZ);
580 for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
581 cp < &bp->b_un.b_buf[sblock.fs_bsize];
582 cp += DIRBLKSIZ)
583 bcopy((char *)&emptydir, cp, sizeof emptydir);
584 dirty(bp);
585 bp = getdirblk(dp->di_db[lastbn + 1],
586 (long)dblksize(&sblock, dp, lastbn + 1));
587 if (bp->b_errs)
588 goto bad;
589 bcopy((char *)&emptydir, bp->b_un.b_buf, sizeof emptydir);
590 pwarn("NO SPACE LEFT IN %s", name);
591 if (preen)
592 printf(" (EXPANDED)\n");
593 else if (reply("EXPAND") == 0)
594 goto bad;
595 dirty(bp);
596 inodirty();
597 return (1);

--- 28 unchanged lines hidden (view full) ---

626 dirp->dot_ino = ino;
627 dirp->dotdot_ino = parent;
628 dp = ginode(ino);
629 bp = getdirblk(dp->di_db[0], sblock.fs_fsize);
630 if (bp->b_errs) {
631 freeino(ino);
632 return (0);
633 }
634 bcopy((char *)dirp, bp->b_un.b_buf, sizeof(struct dirtemplate));
635 for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
636 cp < &bp->b_un.b_buf[sblock.fs_fsize];
637 cp += DIRBLKSIZ)
638 bcopy((char *)&emptydir, cp, sizeof emptydir);
639 dirty(bp);
640 dp->di_nlink = 2;
641 inodirty();
642 if (ino == ROOTINO) {
643 lncntp[ino] = dp->di_nlink;
644 cacheino(dp, ino);
645 return(ino);
646 }

--- 28 unchanged lines hidden (view full) ---

675 inodirty();
676 }
677 freeino(ino);
678}
679
680/*
681 * generate a temporary name for the lost+found directory.
682 */
683int
684lftempname(bufp, ino)
685 char *bufp;
686 ino_t ino;
687{
688 register ino_t in;
689 register char *cp;
690 int namlen;
691

--- 10 unchanged lines hidden (view full) ---

702 *cp = '#';
703 return (namlen);
704}
705
706/*
707 * Get a directory block.
708 * Insure that it is held until another is requested.
709 */
710struct bufarea *
711getdirblk(blkno, size)
712 daddr_t blkno;
713 long size;
714{
715
716 if (pdirbp != 0)
717 pdirbp->b_flags &= ~B_INUSE;
718 pdirbp = getdatablk(blkno, size);
719 return (pdirbp);
720}