/* * Roll the embedded log, if any, and set up the global variables * islog and islogok. */ static int logsetup(caddr_t devstr) { void *buf; extent_block_t *ebp; ml_unit_t *ul; ml_odunit_t *ud; void *ud_buf; int badlog; islog = islogok = 0; if (bflag != 0) return (1); /* can't roll log while alternate sb specified */ /* * Roll the log, if any. A bad sb implies we'll be using * an alternate sb as far as logging goes, so just fail back * to the caller if we can't read the default sb. Suppress * complaints, because the caller will be reading the same * superblock again and running full verification on it, so * whatever is bad will be reported then. */ sblock.fs_logbno = 0; badlog = 0; if (!read_super_block(0)) return (1); /* * Roll the log in 3 cases: * 1. If it's unmounted (mount_point == NULL) and it's not marked * as fully rolled (sblock.fs_rolled != FS_ALL_ROLLED) * 2. If it's mounted and anything other than a sanity * check fsck (mflag) is being done, as we have the current * super block. Note, only a sanity check is done for * root/usr at boot. If a roll were done then the expensive * ufs_flush() gets called, leading to a slower boot. * 3. If anything other then a sanity check (mflag) is being done * to a mounted filesystem while it is in read-only state * (e.g. root during early boot stages) we have to detect this * and have to roll the log as well. NB. the read-only mount * will flip fs_clean from FSLOG to FSSTABLE and marks the * log as FS_NEED_ROLL. */ if (sblock.fs_logbno && (((mount_point == NULL) && (sblock.fs_rolled != FS_ALL_ROLLED)) || ((mount_point != NULL) && !mflag))) { int roll_log_err = 0; if (sblock.fs_ronly && (sblock.fs_clean == FSSTABLE) && (sblock.fs_state + sblock.fs_time == FSOKAY)) { /* * roll the log without a mount */ flush_fs(); } if (sblock.fs_clean == FSLOG && (sblock.fs_state + sblock.fs_time == FSOKAY)) { if (rl_roll_log(devstr) != RL_SUCCESS) roll_log_err = 1; } if (roll_log_err) { (void) printf("Can't roll the log for %s.\n", devstr); /* * There are two cases where we want to set * an error code and return: * - We're preening * - We're not on a live root and the user * chose *not* to ignore the log * Otherwise, we want to mark the log as bad * and continue to check the filesystem. This * has the side effect of destroying the log. */ if (preen || (!hotroot && reply( "DISCARDING THE LOG MAY DISCARD PENDING TRANSACTIONS.\n" "DISCARD THE LOG AND CONTINUE") == 0)) { exitstat = EXERRFATAL; return (0); } ++badlog; } } /* Logging UFS may be enabled */ if (sblock.fs_logbno) { ++islog; /* log is not okay; check the fs */ if (FSOKAY != (sblock.fs_state + sblock.fs_time)) return (1); /* * If logging or (stable and mounted) then continue */ if (!((sblock.fs_clean == FSLOG) || (sblock.fs_clean == FSSTABLE) && (mount_point != NULL))) return (1); /* get the log allocation block */ buf = malloc(dev_bsize); if (buf == NULL) { return (1); } ud_buf = malloc(dev_bsize); if (ud_buf == NULL) { free(buf); return (1); } (void) fsck_bread(fsreadfd, buf, logbtodb(&sblock, sblock.fs_logbno), dev_bsize); ebp = (extent_block_t *)buf; /* log allocation block is not okay; check the fs */ if (ebp->type != LUFS_EXTENTS) { free(buf); free(ud_buf); return (1); } /* get the log state block(s) */ if (fsck_bread(fsreadfd, ud_buf, (logbtodb(&sblock, ebp->extents[0].pbno)), dev_bsize)) { (void) fsck_bread(fsreadfd, ud_buf, (logbtodb(&sblock, ebp->extents[0].pbno)) + 1, dev_bsize); } ud = (ml_odunit_t *)ud_buf; ul = (ml_unit_t *)malloc(sizeof (*ul)); if (ul == NULL) { free(buf); free(ud_buf); return (1); } ul->un_ondisk = *ud; /* log state is okay; don't need to check the fs */ if ((ul->un_chksum == ul->un_head_ident + ul->un_tail_ident) && (ul->un_version == LUFS_VERSION_LATEST) && (ul->un_badlog == 0) && (!badlog)) { ++islogok; } free(ud_buf); free(buf); free(ul); } return (1); }
void check(char *file) { int i, j, c; fi = open64(file, 0); if (fi < 0) { (void) fprintf(stderr, "ncheck: cannot open %s\n", file); nerror++; return; } nhent = 0; (void) printf("%s:\n", file); sync(); bread((diskaddr_t)SBLOCK, (char *)&sblock, SBSIZE); if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != MTB_UFS_MAGIC)) { (void) printf("%s: not a ufs file system\n", file); nerror++; return; } if ((sblock.fs_magic == FS_MAGIC) && ((sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2) && (sblock.fs_version != UFS_VERSION_MIN))) { (void) printf("%s: unrecognized ufs version number %d\n", file, sblock.fs_version); nerror++; return; } if ((sblock.fs_magic == MTB_UFS_MAGIC) && ((sblock.fs_version > MTB_UFS_VERSION_1) || (sblock.fs_version < MTB_UFS_VERSION_MIN))) { (void) printf("%s: unrecognized ufs version number %d\n", file, sblock.fs_version); nerror++; return; } /* If fs is logged, roll the log. */ if (sblock.fs_logbno) { switch (rl_roll_log(file)) { case RL_SUCCESS: /* * Reread the superblock. Rolling the log may have * changed it. */ bread((diskaddr_t)SBLOCK, (char *)&sblock, SBSIZE); break; case RL_SYSERR: (void) printf("Warning: cannot roll log for %s. %s\n", file, strerror(errno)); break; default: (void) printf("Warning: cannot roll log for %s.\n", file); break; } } itab = (struct dinode *)extend_tbl((uchar_t *)itab, &itab_size, (unsigned)(sblock.fs_ipg * sizeof (struct dinode))); if (itab == 0) { (void) fprintf(stderr, "ncheck: not enough memory for itab table\n"); nerror++; return; } hsize = sblock.fs_ipg * sblock.fs_ncg - sblock.fs_cstotal.cs_nifree + 1; htab = (struct htab *)extend_tbl((uchar_t *)htab, &htab_size, (unsigned)(hsize * sizeof (struct htab))); if (htab == 0) { (void) fprintf(stderr, "ncheck: not enough memory for htab table\n"); nerror++; return; } if (!extend_strngtab(AVG_PATH_LEN * hsize)) { (void) printf("not enough memory to allocate tables\n"); nerror++; return; } strngloc = 0; ino = 0; for (c = 0; c < sblock.fs_ncg; c++) { bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, (int)(sblock.fs_ipg * sizeof (struct dinode))); for (j = 0; j < sblock.fs_ipg; j++) { if (itab[j].di_smode != 0) { itab[j].di_mode = itab[j].di_smode; if (itab[j].di_suid != UID_LONG) itab[j].di_uid = itab[j].di_suid; if (itab[j].di_sgid != GID_LONG) itab[j].di_gid = itab[j].di_sgid; pass1(&itab[j]); } ino++; } } ilist[ilist_index++].ino = 0; if (ilist_index > MAX_ILIST_INDEX()) extend_ilist(); ino = 0; for (c = 0; c < sblock.fs_ncg; c++) { bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, (int)(sblock.fs_ipg * sizeof (struct dinode))); for (j = 0; j < sblock.fs_ipg; j++) { if (itab[j].di_smode != 0) { itab[j].di_mode = itab[j].di_smode; pass2(&itab[j]); } ino++; } } ino = 0; for (c = 0; c < sblock.fs_ncg; c++) { bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, (int)(sblock.fs_ipg * sizeof (struct dinode))); for (j = 0; j < sblock.fs_ipg; j++) { if (itab[j].di_smode != 0) { itab[j].di_mode = itab[j].di_smode; pass3(&itab[j]); } ino++; } } (void) close(fi); /* * Clear those elements after inodes specified by "-i" out of * ilist. */ for (i = iflg; i < ilist_index; i++) { ilist[i].ino = 0; } ilist_index = iflg; }
void check(char *file) { int i, j, c; fi = open64(file, 0); if (fi < 0) { (void) fprintf(stderr, "ff: cannot open %s\n", file); nerror++; return; } nhent = 0; (void) printf("%s:\n", file); sync(); bread(SBLOCK, (char *)&sblock, SBSIZE); if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != MTB_UFS_MAGIC)) { (void) fprintf(stderr, "%s: not a ufs file system\n", file); nerror++; return; } if (sblock.fs_magic == FS_MAGIC && (sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && sblock.fs_version != UFS_VERSION_MIN)) { (void) fprintf(stderr, "%s: unrecognized version of UFS: %d\n", file, sblock.fs_version); nerror++; return; } if (sblock.fs_magic == MTB_UFS_MAGIC && (sblock.fs_version > MTB_UFS_VERSION_1 || sblock.fs_version < MTB_UFS_VERSION_MIN)) { (void) fprintf(stderr, "%s: unrecognized version of UFS: %d\n", file, sblock.fs_version); nerror++; return; } /* If fs is logged, roll the log. */ if (sblock.fs_logbno) { switch (rl_roll_log(file)) { case RL_SUCCESS: /* * Reread the superblock. Rolling the log may have * changed it. */ bread(SBLOCK, (char *)&sblock, SBSIZE); break; case RL_SYSERR: (void) printf("Warning: Cannot roll log for %s. %s\n", file, strerror(errno)); break; default: (void) printf("Warning: Cannot roll log for %s.\n ", file); break; } } itab = (struct dinode *)calloc(sblock.fs_ipg, sizeof (struct dinode)); imax = sblock.fs_ncg * sblock.fs_ipg; hsize = sblock.fs_ipg * sblock.fs_ncg - sblock.fs_cstotal.cs_nifree + 1; htab = (struct htab *)calloc(hsize, sizeof (struct htab)); if (!extend_strngtab(AVG_PATH_LEN * hsize)) { (void) printf("not enough memory to allocate tables\n"); nerror++; return; } strngloc = 0; if ((itab == NULL) || (htab == NULL)) { (void) printf("not enough memory to allocate tables\n"); nerror++; return; } ino = 0; for (c = 0; c < sblock.fs_ncg; c++) { bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, (int)(sblock.fs_ipg * sizeof (struct dinode))); for (j = 0; j < sblock.fs_ipg; j++) { if (itab[j].di_smode != 0) { itab[j].di_mode = itab[j].di_smode; if (itab[j].di_suid != (o_uid_t)UID_LONG) itab[j].di_uid = (unsigned int)itab[j].di_suid; if (itab[j].di_sgid != GID_LONG) itab[j].di_gid = (unsigned int)itab[j].di_sgid; pass1(&itab[j]); } ino++; } } ilist[nxfile+1].ino = 0; ino = 0; for (c = 0; c < sblock.fs_ncg; c++) { bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, (int)(sblock.fs_ipg * sizeof (struct dinode))); for (j = 0; j < sblock.fs_ipg; j++) { if (itab[j].di_smode != 0) { itab[j].di_mode = itab[j].di_smode; pass2(&itab[j]); } ino++; } } ino = 0; for (c = 0; c < sblock.fs_ncg; c++) { bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab, (int)(sblock.fs_ipg * sizeof (struct dinode))); for (j = 0; j < sblock.fs_ipg; j++) { if (itab[j].di_smode != 0) { itab[j].di_mode = itab[j].di_smode; pass3(&itab[j]); } ino++; } } (void) close(fi); for (i = iflg; i < NB; i++) ilist[i].ino = 0; nxfile = iflg; free(itab); free(htab); free(strngtab); }