/* * make an entry in a directory */ int makeentry(ufs1_ino_t parent, ufs1_ino_t ino, char *name) { struct ufs1_dinode *dp; struct inodesc idesc; char pathbuf[MAXPATHLEN + 1]; if (parent < ROOTINO || parent >= maxino || ino < ROOTINO || ino >= maxino) return (0); memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = DATA; idesc.id_func = mkentry; idesc.id_number = parent; idesc.id_parent = ino; /* this is the inode to enter */ idesc.id_fix = DONTKNOW; idesc.id_name = name; dp = ginode(parent); if (dp->di_size % DIRBLKSIZ) { dp->di_size = roundup(dp->di_size, DIRBLKSIZ); inodirty(); } if ((ckinode(dp, &idesc) & ALTERED) != 0) return (1); getpathname(pathbuf, parent, parent); dp = ginode(parent); if (expanddir(dp, pathbuf) == 0) return (0); return (ckinode(dp, &idesc) & ALTERED); }
/* * make an entry in a directory */ int makeentry(ino_t parent, ino_t ino, const char *name) { union dinode *dp; struct inodesc idesc; char pathbuf[MAXPATHLEN + 1]; if (parent < ROOTINO || parent >= maxino || ino < ROOTINO || ino >= maxino) return (0); memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = DATA; idesc.id_func = mkentry; idesc.id_number = parent; idesc.id_parent = ino; /* this is the inode to enter */ idesc.id_fix = DONTKNOW; idesc.id_name = strdup(name); dp = ginode(parent); if (DIP(dp, di_size) % DIRBLKSIZ) { DIP_SET(dp, di_size, roundup(DIP(dp, di_size), DIRBLKSIZ)); inodirty(); } if ((ckinode(dp, &idesc) & ALTERED) != 0) return (1); getpathname(pathbuf, parent, parent); dp = ginode(parent); if (expanddir(dp, pathbuf) == 0) return (0); return (ckinode(dp, &idesc) & ALTERED); }
/* * make an entry in a directory */ int makeentry(ino_t parent, ino_t ino, const char *name) { struct ext2fs_dinode *dp; struct inodesc idesc; char pathbuf[MAXPATHLEN + 1]; if ((parent < EXT2_FIRSTINO && parent != EXT2_ROOTINO) || parent >= maxino || (ino < EXT2_FIRSTINO && ino < EXT2_ROOTINO) || ino >= maxino) return (0); memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = DATA; idesc.id_func = mkentry; idesc.id_number = parent; idesc.id_parent = ino; /* this is the inode to enter */ idesc.id_fix = DONTKNOW; idesc.id_name = name; dp = ginode(parent); if (inosize(dp) % sblock.e2fs_bsize) { inossize(dp, roundup(inosize(dp), sblock.e2fs_bsize)); inodirty(); } if ((ckinode(dp, &idesc) & ALTERED) != 0) return (1); getpathname(pathbuf, sizeof(pathbuf), parent, parent); dp = ginode(parent); if (expanddir(dp, pathbuf) == 0) return (0); return (ckinode(dp, &idesc) & ALTERED); }
/* * allocate a new directory */ int allocdir(ino_t parent, ino_t request, int mode) { ino_t ino; struct ext2fs_dinode *dp; struct bufarea *bp; struct ext2fs_dirtemplate *dirp; ino = allocino(request, IFDIR|mode); dirhead.dot_reclen = h2fs16(12); /* XXX */ dirhead.dotdot_reclen = h2fs16(sblock.e2fs_bsize - 12); /* XXX */ dirhead.dot_namlen = 1; if (sblock.e2fs.e2fs_rev > E2FS_REV0 && (sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) dirhead.dot_type = EXT2_FT_DIR; else dirhead.dot_type = 0; dirhead.dotdot_namlen = 2; if (sblock.e2fs.e2fs_rev > E2FS_REV0 && (sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) dirhead.dotdot_type = EXT2_FT_DIR; else dirhead.dotdot_type = 0; dirp = &dirhead; dirp->dot_ino = h2fs32(ino); dirp->dotdot_ino = h2fs32(parent); dp = ginode(ino); bp = getdirblk(fs2h32(dp->e2di_blocks[0]), sblock.e2fs_bsize); if (bp->b_errs) { freeino(ino); return (0); } memcpy(bp->b_un.b_buf, dirp, sizeof(struct ext2fs_dirtemplate)); dirty(bp); dp->e2di_nlink = h2fs16(2); inodirty(); if (ino == EXT2_ROOTINO) { lncntp[ino] = fs2h16(dp->e2di_nlink); cacheino(dp, ino); return(ino); } if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) { freeino(ino); return (0); } cacheino(dp, ino); statemap[ino] = statemap[parent]; if (statemap[ino] == DSTATE) { lncntp[ino] = fs2h16(dp->e2di_nlink); lncntp[parent]++; } dp = ginode(parent); dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) + 1); inodirty(); return (ino); }
void adjust(struct inodesc *idesc, int lcnt) { struct ufs1_dinode *dp; int saveresolved; dp = ginode(idesc->id_number); if (dp->di_nlink == lcnt) { /* * If we have not hit any unresolved problems, are running * in preen mode, and are on a filesystem using soft updates, * then just toss any partially allocated files. */ if (resolved && preen && usedsoftdep) { clri(idesc, "UNREF", 1); return; } else { /* * The filesystem can be marked clean even if * a file is not linked up, but is cleared. * Hence, resolved should not be cleared when * linkup is answered no, but clri is answered yes. */ saveresolved = resolved; if (linkup(idesc->id_number, (ufs1_ino_t)0, NULL) == 0) { resolved = saveresolved; clri(idesc, "UNREF", 0); return; } /* * Account for the new reference created by linkup(). */ dp = ginode(idesc->id_number); lcnt--; } } if (lcnt != 0) { pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : ((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE")); pinode(idesc->id_number); printf(" COUNT %d SHOULD BE %d", dp->di_nlink, dp->di_nlink - lcnt); if (preen || usedsoftdep) { if (lcnt < 0) { printf("\n"); pfatal("LINK COUNT INCREASING"); } if (preen) printf(" (ADJUSTED)\n"); } if (preen || reply("ADJUST") == 1) { dp->di_nlink -= lcnt; inodirty(); } } }
/* * Find a pathname */ void getpathname(char *namebuf, ufs1_ino_t curdir, ufs1_ino_t ino) { int len; char *cp; struct inodesc idesc; static int busy = 0; if (curdir == ino && ino == ROOTINO) { strcpy(namebuf, "/"); return; } if (busy || (inoinfo(curdir)->ino_state != DSTATE && inoinfo(curdir)->ino_state != DFOUND)) { strcpy(namebuf, "?"); return; } busy = 1; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = DATA; idesc.id_fix = IGNORE; cp = &namebuf[MAXPATHLEN - 1]; *cp = '\0'; if (curdir != ino) { idesc.id_parent = curdir; goto namelookup; } while (ino != ROOTINO) { idesc.id_number = ino; idesc.id_func = findino; idesc.id_name = ".."; if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) break; namelookup: idesc.id_number = idesc.id_parent; idesc.id_parent = ino; idesc.id_func = findname; idesc.id_name = namebuf; if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) break; len = strlen(namebuf); cp -= len; memmove(cp, namebuf, (size_t)len); *--cp = '/'; if (cp < &namebuf[MAXNAMLEN]) break; ino = idesc.id_number; } busy = 0; if (ino != ROOTINO) *--cp = '?'; memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); }
/* * Find a pathname */ void getpathname(char *namebuf, size_t buflen, ino_t curdir, ino_t ino) { size_t len; char *cp; struct inodesc idesc; static int busy = 0; if (curdir == ino && ino == EXT2_ROOTINO) { (void)strlcpy(namebuf, "/", buflen); return; } if (busy || (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) { (void)strlcpy(namebuf, "?", buflen); return; } busy = 1; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = DATA; idesc.id_fix = IGNORE; cp = &namebuf[buflen - 1]; *cp = '\0'; if (curdir != ino) { idesc.id_parent = curdir; goto namelookup; } while (ino != EXT2_ROOTINO) { idesc.id_number = ino; idesc.id_func = findino; idesc.id_name = ".."; if ((ckinode(ginode(ino), &idesc) & FOUND) == 0) break; namelookup: idesc.id_number = idesc.id_parent; idesc.id_parent = ino; idesc.id_func = findname; idesc.id_name = namebuf; if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0) break; len = strlen(namebuf); cp -= len; memcpy(cp, namebuf, len); *(--cp) = '/'; if (cp < &namebuf[EXT2FS_MAXNAMLEN]) break; ino = idesc.id_number; } busy = 0; if (ino != EXT2_ROOTINO) *(--cp) = '?'; memcpy(namebuf, cp, (size_t)(&namebuf[buflen] - cp)); }
/* * allocate a new directory */ ino_t allocdir(ino_t parent, ino_t request, int mode) { ino_t ino; char *cp; union dinode *dp; struct bufarea *bp; struct inoinfo *inp; struct dirtemplate *dirp; ino = allocino(request, IFDIR|mode); dirp = &dirhead; dirp->dot_ino = ino; dirp->dotdot_ino = parent; dp = ginode(ino); bp = getdirblk(DIP(dp, di_db[0]), sblock.fs_fsize); if (bp->b_errs) { freeino(ino); return (0); } memmove(bp->b_un.b_buf, dirp, sizeof(struct dirtemplate)); for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; cp < &bp->b_un.b_buf[sblock.fs_fsize]; cp += DIRBLKSIZ) memmove(cp, &emptydir, sizeof emptydir); dirty(bp); DIP_SET(dp, di_nlink, 2); inodirty(); if (ino == ROOTINO) { inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink); cacheino(dp, ino); return(ino); } if (!INO_IS_DVALID(parent)) { freeino(ino); return (0); } cacheino(dp, ino); inp = getinoinfo(ino); inp->i_parent = parent; inp->i_dotdot = parent; inoinfo(ino)->ino_state = inoinfo(parent)->ino_state; if (inoinfo(ino)->ino_state == DSTATE) { inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink); inoinfo(parent)->ino_linkcnt++; } dp = ginode(parent); DIP_SET(dp, di_nlink, DIP(dp, di_nlink) + 1); inodirty(); return (ino); }
/* * allocate a new directory */ ufs1_ino_t allocdir(ufs1_ino_t parent, ufs1_ino_t request, int mode) { ufs1_ino_t ino; char *cp; struct ufs1_dinode *dp; struct bufarea *bp; struct dirtemplate *dirp; ino = allocino(request, IFDIR|mode); if (newinofmt) dirp = &dirhead; else dirp = (struct dirtemplate *)&odirhead; dirp->dot_ino = ino; dirp->dotdot_ino = parent; dp = ginode(ino); bp = getdirblk(dp->di_db[0], sblock.fs_fsize); if (bp->b_errs) { freeino(ino); return (0); } memmove(bp->b_un.b_buf, dirp, sizeof(struct dirtemplate)); for (cp = &bp->b_un.b_buf[DIRBLKSIZ]; cp < &bp->b_un.b_buf[sblock.fs_fsize]; cp += DIRBLKSIZ) memmove(cp, &emptydir, sizeof emptydir); dirty(bp); dp->di_nlink = 2; inodirty(); if (ino == ROOTINO) { inoinfo(ino)->ino_linkcnt = dp->di_nlink; cacheino(dp, ino); return(ino); } if (inoinfo(parent)->ino_state != DSTATE && inoinfo(parent)->ino_state != DFOUND) { freeino(ino); return (0); } cacheino(dp, ino); inoinfo(ino)->ino_state = inoinfo(parent)->ino_state; if (inoinfo(ino)->ino_state == DSTATE) { inoinfo(ino)->ino_linkcnt = dp->di_nlink; inoinfo(parent)->ino_linkcnt++; } dp = ginode(parent); dp->di_nlink++; inodirty(); return (ino); }
void pinode(ufs1_ino_t ino) { struct ufs1_dinode *dp; char *p; struct passwd *pw; time_t t; printf(" I=%lu ", (u_long)ino); if (ino < ROOTINO || ino > maxino) return; dp = ginode(ino); printf(" OWNER="); if ((pw = getpwuid((int)dp->di_uid)) != NULL) printf("%s ", pw->pw_name); else printf("%u ", (unsigned)dp->di_uid); printf("MODE=%o\n", dp->di_mode); if (preen) printf("%s: ", cdevname); printf("SIZE=%ju ", (uintmax_t)dp->di_size); t = dp->di_mtime; p = ctime(&t); printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); }
void pass1b(void) { int c, i; struct ufs1_dinode *dp; struct inodesc idesc; ufs1_ino_t inumber; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass1bcheck; duphead = duplist; inumber = 0; for (c = 0; c < sblock.fs_ncg; c++) { if (got_siginfo) { printf("%s: phase 1b: cyl group %d of %d (%d%%)\n", cdevname, c, sblock.fs_ncg, c * 100 / sblock.fs_ncg); got_siginfo = 0; } for (i = 0; i < sblock.fs_ipg; i++, inumber++) { if (inumber < ROOTINO) continue; dp = ginode(inumber); if (dp == NULL) continue; idesc.id_number = inumber; if (inoinfo(inumber)->ino_state != USTATE && (ckinode(dp, &idesc) & STOP)) return; } } }
void pass4(void) { ino_t inumber; struct zlncnt *zlnp; struct ext2fs_dinode *dp; struct inodesc idesc; int n; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass4check; for (inumber = EXT2_ROOTINO; inumber <= lastino; inumber++) { if (inumber < EXT2_FIRSTINO && inumber > EXT2_ROOTINO) continue; idesc.id_number = inumber; switch (statemap[inumber]) { case FSTATE: case DFOUND: n = lncntp[inumber]; if (n) adjust(&idesc, (short)n); else { for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) if (zlnp->zlncnt == inumber) { zlnp->zlncnt = zlnhead->zlncnt; zlnp = zlnhead; zlnhead = zlnhead->next; free((char *)zlnp); clri(&idesc, "UNREF", 1); break; } } break; case DSTATE: clri(&idesc, "UNREF", 1); break; case DCLEAR: dp = ginode(inumber); if (inosize(dp) == 0) { clri(&idesc, "ZERO LENGTH", 1); break; } /* fall through */ case FCLEAR: clri(&idesc, "BAD/DUP", 1); break; case USTATE: break; default: errexit("BAD STATE %d FOR INODE I=%llu\n", statemap[inumber], (unsigned long long)inumber); } } }
void pass1b(void) { int c, i; union dinode *dp; struct inodesc idesc; ino_t inumber; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass1bcheck; duphead = duplist; inumber = 0; info_fn = pass1b_info; for (c = 0; c < sblock.fs_ncg; c++) { for (i = 0; i < sblock.fs_ipg; i++, inumber++) { info_inumber = inumber; if (inumber < ROOTINO) continue; dp = ginode(inumber); if (dp == NULL) continue; idesc.id_number = inumber; if (GET_ISTATE(inumber) != USTATE && (ckinode(dp, &idesc) & STOP)) return; } } info_fn = NULL; }
void adjust(struct inodesc *idesc, short lcnt) { union dinode *dp; dp = ginode(idesc->id_number); if (DIP(dp, di_nlink) == lcnt) { if (linkup(idesc->id_number, 0) == 0) clri(idesc, "UNREF", 0); } else { pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : ((DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE")); pinode(idesc->id_number); printf(" COUNT %d SHOULD BE %d", DIP(dp, di_nlink), DIP(dp, di_nlink) - lcnt); if (preen || usedsoftdep) { if (lcnt < 0) { printf("\n"); pfatal("LINK COUNT INCREASING"); } if (preen) printf(" (ADJUSTED)\n"); } if (preen || reply("ADJUST") == 1) { DIP_SET(dp, di_nlink, DIP(dp, di_nlink) - lcnt); inodirty(); } } }
void pass1b(void) { int c, i; struct ext2fs_dinode *dp; struct inodesc idesc; ino_t inumber; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass1bcheck; duphead = duplist; inumber = 0; for (c = 0; c < sblock.e2fs_ncg; c++) { for (i = 0; i < sblock.e2fs.e2fs_ipg; i++, inumber++) { if ((inumber < EXT2_FIRSTINO) && (inumber != EXT2_ROOTINO)) continue; dp = ginode(inumber); if (dp == NULL) continue; idesc.id_number = inumber; if (statemap[inumber] != USTATE && (ckinode(dp, &idesc) & STOP)) return; } } }
pass1b() { register int c, i; register struct dinode *dp; struct inodesc idesc; ino_t inumber; bzero((char *)&idesc, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass1bcheck; duphead = duplist; inumber = 0; for (c = 0; c < sblock.fs_ncg; c++) { for (i = 0; i < sblock.fs_ipg; i++, inumber++) { if (inumber < ROOTINO) continue; dp = ginode(inumber); if (dp == NULL) continue; idesc.id_number = inumber; if (statemap[inumber] != USTATE && (ckinode(dp, &idesc) & STOP)) return; } } }
void clri(struct inodesc *idesc, const char *type, int flag) { union dinode *dp; dp = ginode(idesc->id_number); if (flag == 1) { pwarn("%s %s", type, (DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE"); pinode(idesc->id_number); } if (preen || reply("CLEAR") == 1) { if (preen) printf(" (CLEARED)\n"); n_files--; if (bkgrdflag == 0) { (void)ckinode(dp, idesc); inoinfo(idesc->id_number)->ino_state = USTATE; clearinode(dp); inodirty(); } else { cmd.value = idesc->id_number; cmd.size = -DIP(dp, di_nlink); if (debug) printf("adjrefcnt ino %ld amt %lld\n", (long)cmd.value, (long long)cmd.size); if (sysctl(adjrefcnt, MIBSIZE, 0, 0, &cmd, sizeof cmd) == -1) rwerror("ADJUST INODE", cmd.value); } } }
void adjust(struct inodesc *idesc, short lcnt) { struct ext2fs_dinode *dp; dp = ginode(idesc->id_number); if (fs2h16(dp->e2di_nlink) == lcnt) { if (linkup(idesc->id_number, (ino_t)0) == 0) clri(idesc, "UNREF", 0); } else { pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : ((fs2h16(dp->e2di_mode) & IFMT) == IFDIR ? "DIR" : "FILE")); pinode(idesc->id_number); printf(" COUNT %d SHOULD BE %d", fs2h16(dp->e2di_nlink), fs2h16(dp->e2di_nlink) - lcnt); if (preen) { if (lcnt < 0) { printf("\n"); pfatal("LINK COUNT INCREASING"); } printf(" (ADJUSTED)\n"); } if (preen || reply("ADJUST") == 1) { dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) - lcnt); inodirty(); } } }
void pinode(ino_t ino) { struct ufs1_dinode *dp; char *p; struct passwd *pw; time_t t; printf(" I=%llu ", (unsigned long long)ino); if (ino < ROOTINO || ino >= maxino) return; dp = ginode(ino); if (dp) { printf(" OWNER="); #ifndef SMALL if (Uflag && (pw = getpwuid((int) dp->di_uid)) != 0) printf("%s ", pw->pw_name); else #endif printf("%u ", (unsigned) dp->di_uid); printf("MODE=%o\n", dp->di_mode); if (preen) printf("%s: ", cdevname()); printf("SIZE=%llu ", (unsigned long long) dp->di_size); t = dp->di_mtime; p = ctime(&t); printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); } }
/* * allocate an unused inode */ ino_t allocino(ino_t request, int type) { ino_t ino; union dinode *dp; struct bufarea *cgbp; struct cg *cgp; int cg; if (request == 0) request = ROOTINO; else if (inoinfo(request)->ino_state != USTATE) return (0); for (ino = request; ino < maxino; ino++) if (inoinfo(ino)->ino_state == USTATE) break; if (ino == maxino) return (0); cg = ino_to_cg(&sblock, ino); cgbp = cgget(cg); cgp = cgbp->b_un.b_cg; if (!check_cgmagic(cg, cgbp)) return (0); setbit(cg_inosused(cgp), ino % sblock.fs_ipg); cgp->cg_cs.cs_nifree--; switch (type & IFMT) { case IFDIR: inoinfo(ino)->ino_state = DSTATE; cgp->cg_cs.cs_ndir++; break; case IFREG: case IFLNK: inoinfo(ino)->ino_state = FSTATE; break; default: return (0); } dirty(cgbp); dp = ginode(ino); DIP_SET(dp, di_db[0], allocblk((long)1)); if (DIP(dp, di_db[0]) == 0) { inoinfo(ino)->ino_state = USTATE; return (0); } DIP_SET(dp, di_mode, type); DIP_SET(dp, di_flags, 0); DIP_SET(dp, di_atime, time(NULL)); DIP_SET(dp, di_ctime, DIP(dp, di_atime)); DIP_SET(dp, di_mtime, DIP(dp, di_ctime)); DIP_SET(dp, di_mtimensec, 0); DIP_SET(dp, di_ctimensec, 0); DIP_SET(dp, di_atimensec, 0); DIP_SET(dp, di_size, sblock.fs_fsize); DIP_SET(dp, di_blocks, btodb(sblock.fs_fsize)); n_files++; inodirty(); inoinfo(ino)->ino_type = IFTODT(type); return (ino); }
void pass4() { register u_int32_t inumber; register struct zlncnt *zlnp; struct dinode *dp; struct inodesc idesc; int n; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass4check; for (inumber = ROOTINO; inumber <= lastino; inumber++) { idesc.id_number = inumber; switch (statemap[inumber]) { case FSTATE: case DFOUND: n = lncntp[inumber]; if (n) adjust(&idesc, (short)n); else { for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) if (zlnp->zlncnt == inumber) { zlnp->zlncnt = zlnhead->zlncnt; zlnp = zlnhead; zlnhead = zlnhead->next; free((char *)zlnp); clri(&idesc, "UNREF", 1); break; } } break; case DSTATE: clri(&idesc, "UNREF", 1); break; case DCLEAR: dp = ginode(inumber); if (dp->di_size == 0) { clri(&idesc, "ZERO LENGTH", 1); break; } /* fall through */ case FCLEAR: clri(&idesc, "BAD/DUP", 1); break; case USTATE: break; default: errx(EEXIT, "BAD STATE %d FOR INODE I=%d", statemap[inumber], inumber); } } }
/* * allocate an unused inode */ ufs1_ino_t allocino(ufs1_ino_t request, int type) { ufs1_ino_t ino; struct ufs1_dinode *dp; struct cg *cgp = &cgrp; int cg; if (request == 0) request = ROOTINO; else if (inoinfo(request)->ino_state != USTATE) return (0); for (ino = request; ino < maxino; ino++) if (inoinfo(ino)->ino_state == USTATE) break; if (ino == maxino) return (0); cg = ino_to_cg(&sblock, ino); getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); if (!cg_chkmagic(cgp)) pfatal("CG %d: BAD MAGIC NUMBER\n", cg); setbit(cg_inosused(cgp), ino % sblock.fs_ipg); cgp->cg_cs.cs_nifree--; switch (type & IFMT) { case IFDIR: inoinfo(ino)->ino_state = DSTATE; cgp->cg_cs.cs_ndir++; break; case IFREG: case IFLNK: inoinfo(ino)->ino_state = FSTATE; break; default: return (0); } cgdirty(); dp = ginode(ino); dp->di_db[0] = allocblk((long)1); if (dp->di_db[0] == 0) { inoinfo(ino)->ino_state = USTATE; return (0); } dp->di_mode = type; dp->di_flags = 0; dp->di_atime = time(NULL); dp->di_mtime = dp->di_ctime = dp->di_atime; dp->di_mtimensec = dp->di_ctimensec = dp->di_atimensec = 0; dp->di_size = sblock.fs_fsize; dp->di_blocks = btodb(sblock.fs_fsize); n_files++; inodirty(); if (newinofmt) inoinfo(ino)->ino_type = IFTODT(type); return (ino); }
/* * free a directory inode */ static void freedir(ufs1_ino_t ino, ufs1_ino_t parent) { struct ufs1_dinode *dp; if (ino != parent) { dp = ginode(parent); dp->di_nlink--; inodirty(); } freeino(ino); }
/* * free a directory inode */ static void freedir(ino_t ino, ino_t parent) { union dinode *dp; if (ino != parent) { dp = ginode(parent); DIP_SET(dp, nlink, iswap16(iswap16(DIP(dp, nlink)) - 1)); inodirty(); } freeino(ino); }
/* * free a directory inode */ static void freedir(ino_t ino, ino_t parent) { struct ext2fs_dinode *dp; if (ino != parent) { dp = ginode(parent); dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) - 1); inodirty(); } freeino(ino); }
/* * free a directory inode */ static void freedir(ino_t ino, ino_t parent) { union dinode *dp; if (ino != parent) { dp = ginode(parent); DIP_SET(dp, di_nlink, DIP(dp, di_nlink) - 1); inodirty(); } freeino(ino); }
/* * fix an entry in a directory. */ int changeino(ino_t dir, const char *name, ino_t newnum) { struct inodesc idesc; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = DATA; idesc.id_func = chgino; idesc.id_number = dir; idesc.id_fix = DONTKNOW; idesc.id_name = strdup(name); idesc.id_parent = newnum; /* new value for name */ return (ckinode(ginode(dir), &idesc)); }
/* * deallocate an inode */ void freeino(ufs1_ino_t ino) { struct inodesc idesc; struct ufs1_dinode *dp; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass4check; idesc.id_number = ino; dp = ginode(ino); ckinode(dp, &idesc); clearinode(dp); inodirty(); inoinfo(ino)->ino_state = USTATE; n_files--; }
/* * Do fixup for bad acl/attr references. If PARENT is -1, then * we assume we're working on a shadow, otherwise an extended attribute. * FMT must be a printf format string, with one %d directive for * the inode number. */ static void clear_attr_acl(fsck_ino_t inumber, fsck_ino_t parent, char *fmt) { fsck_ino_t victim = inumber; struct dinode *dp; if (parent != -1) victim = parent; if (fmt != NULL) { if (parent == -1) pwarn(fmt, (int)inumber); else pwarn(fmt, (int)inumber, (int)parent); } if (debug) (void) printf("parent file/dir I=%d\nvictim I=%d", (int)parent, (int)victim); if (!preen && (reply("REMOVE REFERENCE") == 0)) { iscorrupt = 1; return; } dp = ginode(victim); if (parent == -1) { /* * The file had a bad shadow/acl, so lock it down * until someone can protect it the way they need it * to be (i.e., be conservatively paranoid). */ dp->di_shadow = 0; dp->di_mode &= IFMT; } else { dp->di_oeftflag = 0; } inodirty(); if (preen) (void) printf(" (CORRECTED)\n"); }
void fileerror(ino_t cwd, ino_t ino, const char *errmesg) { struct ext2fs_dinode *dp; char pathbuf[MAXPATHLEN + 1]; pwarn("%s ", errmesg); pinode(ino); printf("\n"); getpathname(pathbuf, sizeof(pathbuf), cwd, ino); if ((ino < EXT2_FIRSTINO && ino != EXT2_ROOTINO) || ino > maxino) { pfatal("NAME=%s\n", pathbuf); return; } dp = ginode(ino); if (ftypeok(dp)) pfatal("%s=%s\n", (fs2h16(dp->e2di_mode) & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf); else pfatal("NAME=%s\n", pathbuf); }