elks-enhanced
public
Read
Owner: themaster
Branch: master
Commits: 6893
Updated: 2026-04-19 00:15
Git CLI clone URL
git clone https://www.xt-emporium.com/git/elks-enhanced.git
Fullscreen desktop URL
Code
Commits
History
Branches
Bug Reports
Discussions
Compare
Settings
elks-enhanced
/
elkscmd
/
busyelks
/
cmd
/
fsck.c
File editor
/* * fsck.c - a file system consistency checker for Linux. * * (C) 1991, 1992 Linus Torvalds. This file may be redistributed * as per the GNU copyleft. */ /* * 09.11.91 - made the first rudimetary functions * * 10.11.91 - updated, does checking, no repairs yet. * Sent out to the mailing-list for testing. * * 14.11.91 - Testing seems to have gone well. Added some * correction-code, and changed some functions. * * 15.11.91 - More correction code. Hopefully it notices most * cases now, and tries to do something about them. * * 16.11.91 - More corrections (thanks to Mika Jalava). Most * things seem to work now. Yeah, sure. * * * 19.04.92 - Had to start over again from this old version, as a * kernel bug ate my enhanced fsck in february. * * 28.02.93 - added support for different directory entry sizes.. * * Sat Mar 6 18:59:42 1993, faith@cs.unc.edu: Output namelen with * super-block information * * Sat Oct 9 11:17:11 1993, faith@cs.unc.edu: make exit status conform * to that required by fsutil * * Mon Jan 3 11:06:52 1994 - Dr. Wettstein (greg%wind.uucp@plains.nodak.edu) * Added support for file system valid flag. Also * added program_version variable and output of * program name and version number when program * is executed. * * I've had no time to add comments - hopefully the function names * are comments enough. As with all file system checkers, this assumes * the file system is quiescent - don't use it on a mounted device * unless you can be sure nobody is writing to it (and remember that the * kernel can write to it when it searches for files). * * Usuage: fsck [-larvsm] device * -l for a listing of all the filenames * -a for automatic repairs (not implemented) * -r for repairs (interactive) (not implemented) * -v for verbose (tells how many files) * -s for super-block info * -m for minix-like "mode not cleared" warnings * -f force filesystem check even if filesystem marked as valid * * The device may be a block device or a image of one, but this isn't * enforced (but it's not much fun on a character device :-). */ #include <stdio.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <ctype.h> #include <stdlib.h> #include <termios.h> #include <sys/stat.h> #include <linuxmt/fs.h> #include <linuxmt/minix_fs.h> #ifndef __linux__ #define volatile #endif #define printd /*printf*/ /* FIXME remove all commented out code with RUBOUT in it */ #define ROOT_INO 1 #define UPPER(size,n) ((size+((n)-1))/(n)) #define BITS_PER_BLOCK (BLOCK_SIZE<<3) static char * program_name = "fsck.minix"; static char * program_version = "1.0 - 12/30/93"; static char * device_name = NULL; static int IN; static int repair=0, automatic=0, verbose=0, list=0, show=0, warn_mode=0, force=0; static int directory=0, regular=0, blockdev=0, chardev=0, links=0, symlinks=0, total=0; static int changed = 0; /* flags if the filesystem has been changed */ static int errors_uncorrected = 0; /* flag if some error was not corrected */ /* static int dirsize = 16; RUBOUT */ /* static int namelen = 14; RUBOUT */ #define DIRSIZE 16 #define NAMELEN 14 /* File-name data */ #define MAX_DEPTH 50 static int name_depth = 0; static char name_list[MAX_DEPTH][NAMELEN+1]; /*static char * inode_buffer = NULL; */ static char inode_buffer[BLOCK_SIZE]; #define Inode (((struct minix_inode *) inode_buffer)-1) static char super_block_buffer[BLOCK_SIZE]; struct minix_super_block * SupeP = (struct minix_super_block *)super_block_buffer; #define Super (*(struct minix_super_block *)super_block_buffer) /* #define SupeP ((struct minix_super_block *)super_block_buffer) */ #define INODES (SupeP->s_ninodes) #define ZONES (SupeP->s_nzones) #define IMAPS (SupeP->s_imap_blocks) #define ZMAPS (SupeP->s_zmap_blocks) #define FIRSTZONE (SupeP->s_firstdatazone) #define ZONESIZE (SupeP->s_log_zone_size) #define MAXSIZE (SupeP->s_max_size) #define MAGIC (SupeP->s_magic) #define INODE_SIZE (sizeof(struct minix_inode)) #define INODE_BLOCKS UPPER(INODES,MINIX_INODES_PER_BLOCK) #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS) static char inode_map[BLOCK_SIZE * MINIX_I_MAP_SLOTS]; static char zone_map[BLOCK_SIZE * 2]; static unsigned char * inode_count = NULL; static unsigned char * zone_count = NULL; void recursive_check(unsigned int ino); #define bit(addr,bit) (test_bit((bit),(addr)) != 0) #define setbit(addr,bit) (set_bit((bit),(addr)) != 0) #define clrbit(addr,bit) (clear_bit((bit),(addr)) != 0) #define inode_in_use(x) (bit(inode_map,(x))) #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1)) #define mark_inode(x) (setbit(inode_map,(x)),changed=1) #define unmark_inode(x) (clrbit(inode_map,(x)),changed=1) #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1),changed=1) #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1),changed=1) /* * Volatile to let gcc know that this doesn't return. When trying * to compile this under minix, volatile gives a warning, as * exit() isn't defined as volatile under minix. */ volatile void fsck_fatal_error(const char * fmt_string, int status) { fprintf(stderr,fmt_string,program_name,device_name); exit(status); } #define usage() fsck_fatal_error("Usage: %s [-larvsmf] /dev/name\n",16) #define die(str) fsck_fatal_error("%s: " str "\n",8) int mapped_block = -1; /* Block in the inode area that is mapped */ int mapped_dirty = 0; /* non-zero indicates inode block has been altered */ void unmap_inode_buffer() /* Write the inode block in inode_buffer back to disk if it is dirty. */ { printd("Unmap requested: "); if (mapped_dirty == 0) { /* Nothing to do. */ printd("not dirty\n"); return; } if (mapped_block < 0) { /* Nothing to do. */ printd("none mapped\n"); return; } /* Seek to after the Superblock, inode maps and zone maps */ lseek(IN, (off_t)((2 + IMAPS + ZMAPS) * BLOCK_SIZE), SEEK_SET); /* Seek to the block we have to write */ if (mapped_block > 1) { lseek(IN, (off_t)((mapped_block) * BLOCK_SIZE), SEEK_CUR); } if (BLOCK_SIZE != write(IN, inode_buffer, BLOCK_SIZE)) { die("Unable to write inodes"); } mapped_dirty = 0; printd("Block %d unmapped.", mapped_block); } void inode_dump(struct minix_inode * ptr) { int mode = ptr->i_mode; int i; printf("Mode %d %d %d %d\n", mode & 7, (mode>>4) & 7, (mode>>4) & 7, (mode>>12) & 7); printf("uid %d size %ld gid %d links %d\n", ptr->i_uid, ptr->i_size, ptr->i_gid, ptr->i_nlinks); for(i=0;i<9;i++){ printf("Z%d ", ptr->i_zone[i]); } printf("\n"); } struct minix_inode * map_inode(unsigned int nr) /* Take an inode number and map the 1024 byte block on disk containing this * inode into the inode memory area inode_buffer, returning a pointer to * the inode. */ { int inode_block; /* Block in the inode area we have to map */ int inode_offset; /* Inode offset in current block */ struct minix_inode * inode_ptr; if (!nr || nr >= INODES) return NULL; inode_block = nr >> 5; inode_offset = (nr & 31) - 1; printd("Map of inode %d requested which is no %d in block %d\n", nr, inode_offset, inode_block); inode_ptr = ((struct minix_inode *)inode_buffer) + inode_offset; if (mapped_block != -1) { /* CHECK IF IT IS THE BLOCK WE WANT */ if (inode_block == mapped_block) { /* If so return pointer */ printd("Block was already mapped.\n"); return inode_ptr; } /* WRITE OLD INODE BLOCK BACK TO DISK */ unmap_inode_buffer(); } /* Seek to after the Superblock, inode maps and zone maps */ lseek(IN, (off_t)((2 + IMAPS + ZMAPS) * BLOCK_SIZE), SEEK_SET); /* Seek to the block we have to write */ if (inode_block > 0) { lseek(IN, (off_t)((inode_block) * BLOCK_SIZE), SEEK_CUR); } /* READ In NEW BLOCK FROM DISK */ if (BLOCK_SIZE != read(IN, inode_buffer, BLOCK_SIZE)) { die("Unable to read inodes"); } /* SET mapped */ mapped_block = inode_block; /* RETURN POINTER */ inode_dump(inode_ptr); return inode_ptr; } /* * This simply goes through the file-name data and prints out the * current file. */ void print_current_name(void) { int i=0; while (i<name_depth) printf("/%.*s",14,name_list[i++]); /* FIXME 14 can be integrated */ } int ask(const char * string,int def) { int c; if (!repair) { printf("\n"); errors_uncorrected = 1; return 0; } if (automatic) { printf("\n"); if (!def) errors_uncorrected = 1; return def; } printf(def?"%s (y/n)? ":"%s (n/y)? ",string); for (;;) { fflush(stdout); if ((c=getchar())==EOF) { if (!def) errors_uncorrected = 1; return def; } c=toupper(c); if (c == 'Y') { def = 1; break; } else if (c == 'N') { def = 0; break; } else if (c == ' ' || c == '\n') break; } if (def) printf("y\n"); else { printf("n\n"); errors_uncorrected = 1; } return def; } /* * check_zone_nr checks to see that *nr is a valid zone nr. If it * isn't, it will possibly be repaired. Check_zone_nr sets *corrected * if an error was corrected, and returns the zone (0 for no zone * or a bad zone-number). */ int check_zone_nr(unsigned short * nr, int * corrected) { if (!*nr) return 0; if (*nr < FIRSTZONE) printf("Zone nr < FIRSTZONE in file `"); else if (*nr >= ZONES) printf("Zone nr >= ZONES in file `"); else return *nr; print_current_name(); printf("'."); if (ask("Remove block",1)) { *nr = 0; *corrected = 1; } return 0; } /* * read-block reads block nr into the buffer at addr. */ void read_block(unsigned int nr, char * addr) { int i; off_t dest = (off_t)BLOCK_SIZE * nr; printd("read_block %x %lx ", nr, dest); if (!nr) { memset(addr,0,BLOCK_SIZE); return; } if (dest != lseek(IN, dest, SEEK_SET)) { printf("Read error: unable to seek to block in file '"); print_current_name(); printf("'\n"); memset(addr,0,BLOCK_SIZE); errors_uncorrected = 1; } else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) { printf("Read error: bad block in file '"); print_current_name(); printf("'\n"); memset(addr,0,BLOCK_SIZE); errors_uncorrected = 1; } for(i = 0; i < 16; i++) { printd("%x ", addr[i]); } printd("\n"); } /* * write_block writes block nr to disk. */ void fsck_write_block(unsigned int nr, char * addr) { off_t dest = (off_t)BLOCK_SIZE * nr; if (!nr) return; if (nr < FIRSTZONE || nr >= ZONES) { printf("Internal error: trying to write bad block\n" "Write request ignored\n"); errors_uncorrected = 1; return; } if (dest != lseek(IN, dest, SEEK_SET)) die("seek failed in write_block"); if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) { printf("Write error: bad block in file '"); print_current_name(); printf("'\n"); errors_uncorrected = 1; } } /* * map-block calculates the absolute block nr of a block in a file. * It sets 'changed' if the inode has needed changing, and re-writes * any indirect blocks with errors. */ unsigned int map_block(struct minix_inode * inode, unsigned int blknr) { unsigned short ind[BLOCK_SIZE>>1]; unsigned short dind[BLOCK_SIZE>>1]; int blk_chg, block, result; int i; printd("map_block %x %d (", inode, blknr); for(i = 0; i < 7; i++) { printd("%x ", inode->i_zone[i]); } if (blknr<7) { printd(")direct\n"); return check_zone_nr(inode->i_zone + blknr, &changed); } blknr -= 7; if (blknr<512) { printd(")ind\n"); block = check_zone_nr(inode->i_zone + 7, &changed); read_block(block, (char *) ind); blk_chg = 0; result = check_zone_nr(blknr + ind, &blk_chg); if (blk_chg) fsck_write_block(block, (char *) ind); return result; } printd(")dind\n"); blknr -= 512; block = check_zone_nr(inode->i_zone + 8, &changed); read_block(block, (char *) dind); blk_chg = 0; result = check_zone_nr(dind + (blknr/512), &blk_chg); if (blk_chg) fsck_write_block(block, (char *) dind); block = result; read_block(block, (char *) ind); blk_chg = 0; result = check_zone_nr(ind + (blknr%512), &blk_chg); if (blk_chg) fsck_write_block(block, (char *) ind); return result; } void write_super_block(void) { /* * Set the state of the filesystem based on whether or not there * are uncorrected errors. The filesystem valid flag is * unconditionally set if we get this far. */ SupeP->s_state |= MINIX_VALID_FS; if ( errors_uncorrected ) SupeP->s_state |= MINIX_ERROR_FS; else SupeP->s_state &= ~MINIX_ERROR_FS; if ((off_t)BLOCK_SIZE != lseek(IN, (off_t)BLOCK_SIZE, SEEK_SET)) die("seek failed in write_super_block"); if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE)) die("unable to write super-block"); return; } void write_tables(void) { write_super_block(); if (IMAPS*BLOCK_SIZE != write(IN,inode_map,IMAPS*BLOCK_SIZE)) die("Unable to write inode map"); if (ZMAPS*BLOCK_SIZE != write(IN,zone_map,ZMAPS*BLOCK_SIZE)) die("Unable to write zone map"); unmap_inode_buffer(); /* if (INODE_BUFFER_SIZE != write(IN,inode_buffer,INODE_BUFFER_SIZE)) die("Unable to write inodes"); RUBOUT */ } void read_tables(void) { int foo; /* unsigned int inode_buffer_size = INODE_BUFFER_SIZE; RUBOUT */ memset(inode_map,0,sizeof(inode_map)); memset(zone_map,0,sizeof(zone_map)); if ((off_t)BLOCK_SIZE != (off_t)lseek(IN, (off_t)BLOCK_SIZE, SEEK_SET)) die("seek failed"); if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE)) die("unable to read super block"); if (MAGIC == MINIX_SUPER_MAGIC) { /* namelen = 14; RUBOUT */ /* dirsize = 16; RUBOUT */ } else { die("bad magic number in super-block"); } /*else if (MAGIC == MINIX_SUPER_MAGIC2) { RUBOUT namelen = 30; dirsize = 32; } else */ if (ZONESIZE != 0/* || BLOCK_SIZE != 1024*/) die("Only 1k blocks/zones supported"); if (!IMAPS || IMAPS > MINIX_I_MAP_SLOTS) die("bad s_imap_blocks field in super-block"); if (!ZMAPS || ZMAPS > MINIX_Z_MAP_SLOTS) die("bad s_zmap_blocks field in super-block"); /* inode_buffer = malloc(BLOCK_SIZE); RUBOUT */ if (!inode_buffer) die("Unable to allocate buffer for inodes"); inode_count = malloc(INODES); if (!inode_count) die("Unable to allocate buffer for inode count"); zone_count = malloc(ZONES); if (!zone_count) die("Unable to allocate buffer for zone count"); if (IMAPS*BLOCK_SIZE != read(IN,inode_map,IMAPS*BLOCK_SIZE)) die("Unable to read inode map"); if (ZMAPS*BLOCK_SIZE != read(IN,zone_map,ZMAPS*BLOCK_SIZE)) die("Unable to read zone map"); /* if (inode_buffer_size != (foo = read(IN,inode_buffer,inode_buffer_size))) { die("Unable to read inodes"); } RUBOUT */ if (NORM_FIRSTZONE != FIRSTZONE) { printf("Warning: Firstzone != Norm_firstzone\n"); errors_uncorrected = 1; } if (show) { printf("%d inodes\n",INODES); printf("%d blocks\n",ZONES); printf("Pre-zone blocks 2+%d+%d+%d %d\n", IMAPS, ZMAPS, INODE_BLOCKS, NORM_FIRSTZONE); printf("Firstdatazone=%d (%d)\n",FIRSTZONE,NORM_FIRSTZONE); printf("Zonesize=%d\n",BLOCK_SIZE<<ZONESIZE); printf("Maxsize=%ld\n",MAXSIZE); printf("Filesystem state=%d\n", SupeP->s_state); printf("namelen=14\n\n"); /* RUBOUT */ } } struct minix_inode * get_inode(unsigned int nr) { struct minix_inode * inode; if (!nr || nr >= INODES) return NULL; total++; /* inode = Inode + nr; RUBOUT */ inode = map_inode(nr); if (!inode_count[nr]) { if (!inode_in_use(nr)) { printf("Inode %d marked not used, but used for file '", nr); print_current_name(); printf("'\n"); if (repair) if (ask("Mark in use",1)) mark_inode(nr); else errors_uncorrected = 1; } if (S_ISDIR(inode->i_mode)) directory++; else if (S_ISREG(inode->i_mode)) regular++; else if (S_ISCHR(inode->i_mode)) chardev++; else if (S_ISBLK(inode->i_mode)) blockdev++; else if (S_ISLNK(inode->i_mode)) symlinks++; else if (S_ISSOCK(inode->i_mode)) ; else if (S_ISFIFO(inode->i_mode)) ; else { print_current_name(); printf(" has mode %05o\n",inode->i_mode); } } else links++; if (!++inode_count[nr]) { printf("Warning: inode count too big.\n"); inode_count[nr]--; errors_uncorrected = 1; } return inode; } void check_root(void) { /* struct minix_inode * inode = Inode + ROOT_INO; RUBOUT */ struct minix_inode * inode = map_inode(ROOT_INO); if (!inode || !S_ISDIR(inode->i_mode)) die("root inode isn't a directory"); printf("Root inode is a directory.\n"); } static int add_zone(unsigned short * znr, int * corrected) { int result; int block; printd("add_zone %d\n", * znr); result = 0; block = check_zone_nr(znr, corrected); if (!block) return 0; if (zone_count[block]) { printf("Block has been used before. Now in file `"); print_current_name(); printf("'."); if (ask("Clear",1)) { *znr = 0; block = 0; *corrected = 1; } } if (!block) return 0; if (!zone_in_use(block)) { printf("Block %d in file `",block); print_current_name(); printf("' is marked not in use."); if (ask("Correct",1)) mark_zone(block); } if (!++zone_count[block]) zone_count[block]--; return block; } static void add_zone_ind(unsigned short * znr, int * corrected) { static char blk[BLOCK_SIZE]; int i, chg_blk=0; int block; printd("add_zone_ind %d\n", * znr); block = add_zone(znr, corrected); if (!block) return; read_block(block, blk); for (i=0 ; i < (BLOCK_SIZE>>1) ; i++) add_zone(i + (unsigned short *) blk, &chg_blk); if (chg_blk) fsck_write_block(block, blk); } static void add_zone_dind(unsigned short * znr, int * corrected) { static char blk[BLOCK_SIZE]; int i, blk_chg=0; int block; printd("add_zone_dind %d\n", * znr); block = add_zone(znr, corrected); if (!block) return; read_block(block, blk); for (i=0 ; i < (BLOCK_SIZE>>1) ; i++) add_zone_ind(i + (unsigned short *) blk, &blk_chg); if (blk_chg) fsck_write_block(block, blk); } void check_zones(unsigned int i) { struct minix_inode * inode; printd("check_zones\n"); if (!i || i >= INODES) return; if (inode_count[i] > 1) /* have we counted this file already? */ return; /* inode = Inode + i; RUBOUT */ inode = map_inode(i); if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) return; for (i=0 ; i<7 ; i++) add_zone(i + inode->i_zone, &changed); add_zone_ind(7 + inode->i_zone, &changed); add_zone_dind(8 + inode->i_zone, &changed); printd("check_zones_end\n"); } void fsck_check_file(struct minix_inode * dir, unsigned long offset) { static char blk[BLOCK_SIZE]; struct minix_inode * inode; int ino; char * name; unsigned int block; block = map_block(dir,(unsigned int)(offset >> 10)); read_block(block, blk); name = blk + (offset % BLOCK_SIZE); ino = * (unsigned short *) (name); name += 2; /* ino = * (unsigned short *) blk; */ printd("check_file %x %lx ",ino, offset); printd("\n"); if (ino >= INODES) { print_current_name(); printf(" contains a bad inode number %d for file '", ino); printf("%.*s'.",14,name); /* FIXME 14 can be integrated */ if (ask(" Remove",1)) { *(unsigned short *)(name-2) = 0; fsck_write_block(block, blk); } ino = 0; } inode = get_inode(ino); if (offset == 0L) if (!inode || strcmp(".",name)) { print_current_name(); printf(": bad directory: '.' isn't first\n"); errors_uncorrected = 1; } else return; if (offset == (unsigned long)DIRSIZE) if (!inode || strcmp("..",name)) { print_current_name(); printf(": bad directory: '..' isn't second\n"); errors_uncorrected = 1; } else return; if (!inode) return; if (name_depth < MAX_DEPTH) strncpy(name_list[name_depth],name,NAMELEN); name_depth++; print_current_name(); printf("\n"); if (list) { if (verbose) printf("%6d %07o %3d ",ino,inode->i_mode,inode->i_nlinks); print_current_name(); if (S_ISDIR(inode->i_mode)) printf(":\n"); else printf("\n"); } check_zones(ino); if (inode && S_ISDIR(inode->i_mode)) recursive_check(ino); name_depth--; return; } void recursive_check(unsigned int ino) { struct minix_inode * dir; struct minix_inode mdir; unsigned long offset; printd("recursive_check %d\n", ino); /* dir = Inode + ino; */ dir = map_inode(ino); memcpy(&mdir, dir, sizeof(struct minix_inode)); dir = &mdir; if (!S_ISDIR(dir->i_mode)) die("internal error"); if (dir->i_size < 32L) { print_current_name(); printf(": bad directory: size<32"); errors_uncorrected = 1; } for (offset = 0 ; offset < dir->i_size ; offset += DIRSIZE) fsck_check_file(dir,offset); } int bad_zone(int i) { char buffer[1024]; off_t dest = (off_t)BLOCK_SIZE * i; printd("bad_zone %d\n", i); if (dest != lseek(IN, dest, SEEK_SET)) die("seek failed in bad_zone"); return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE)); } void check_counts(void) { int i; printd("check_counts\n"); for (i=1 ; i < INODES ; i++) { struct minix_inode * inode = map_inode(i); if (!inode_in_use(i) && inode->i_mode && warn_mode) { printf("Inode %d mode not cleared.",i); if (ask("Clear",1)) { inode->i_mode = 0; mapped_dirty++; changed = 1; } } if (!inode_count[i]) { if (!inode_in_use(i)) continue; printf("Inode %d not used, marked used in the bitmap.",i); if (ask("Clear",1)) unmark_inode(i); continue; } if (!inode_in_use(i)) { printf("Inode %d used, marked unused in the bitmap.", i); if (ask("Set",1)) mark_inode(i); } if (inode->i_nlinks != inode_count[i]) { printf("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.", i,inode->i_mode,inode->i_nlinks,inode_count[i]); if (ask("Set i_nlinks to count",1)) { inode->i_nlinks=inode_count[i]; mapped_dirty++; changed=1; } } } for (i=FIRSTZONE ; i < ZONES ; i++) { if (zone_in_use(i) == zone_count[i]) continue; if (!zone_count[i]) { if (bad_zone(i)) continue; printf("Zone %d: marked in use, no file uses it.",i); if (ask("Unmark",1)) unmark_zone(i); continue; } printf("Zone %d: %sin use, counted=%d\n", i,zone_in_use(i)?"":"not ",zone_count[i]); } } int fsck_main(int argc, char ** argv) { struct termios termios,tmp; int i; int count; int retcode = 0; if (argc && *argv) program_name = *argv; if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) die("bad inode size"); while (argc-- > 1) { argv++; if (argv[0][0] != '-') if (device_name) usage(); else device_name = argv[0]; else while (*++argv[0]) switch (argv[0][0]) { case 'l': list=1; break; case 'a': automatic=1; repair=1; break; case 'r': automatic=0; repair=1; break; case 'v': verbose=1; break; case 's': show=1; break; case 'm': warn_mode=1; break; case 'f': force=1; break; default: usage(); } } if (!device_name) usage(); if (repair && !automatic) { if (!isatty(0) || !isatty(1)) die("need terminal for interactive repairs"); tcgetattr(0,&termios); tmp = termios; tmp.c_lflag &= ~(ICANON|ECHO); tcsetattr(0,TCSANOW,&tmp); } IN = open(device_name,repair?O_RDWR:O_RDONLY); if (IN < 0) die("unable to open '%s'"); for (count=0 ; count<3 ; count++) sync(); read_tables(); /* * Determine whether or not we should continue with the checking. * This is based on the status of the filesystem valid and error * flags and whether or not the -f switch was specified on the * command line. */ printf("%s, %s\n", program_name, program_version); if ( !(SupeP->s_state & MINIX_ERROR_FS) && (SupeP->s_state & MINIX_VALID_FS) && !force ) { if (repair) printf("%s is clean, no check.\n", device_name); if (repair && !automatic) tcsetattr(0,TCSANOW,&termios); return retcode; } else if (force) printf("Forcing filesystem check on %s.\n", device_name); else if (repair) printf("Filesystem on %s is dirty, needs checking.\n",\ device_name); check_root(); /* Next 6 lines used to be a pointless check() function */ printd("check\n"); memset(inode_count,0,INODES*sizeof(*inode_count)); memset(zone_count,0,ZONES*sizeof(*zone_count)); check_zones(ROOT_INO); recursive_check(ROOT_INO); check_counts(); if (verbose) { int i, free; for (i=1,free=0 ; i < INODES ; i++) if (!inode_in_use(i)) free++; printf("\n%6d inodes used (%d%%)\n",(INODES-free-1), 100*(INODES-free-1)/(INODES-1)); for (i=FIRSTZONE,free=0 ; i < ZONES ; i++) if (!zone_in_use(i)) free++; printf("%6d zones used (%d%%)\n",(ZONES-free), 100*(ZONES-free)/ZONES); printf("\n%6d regular files\n" "%6d directories\n" "%6d character device files\n" "%6d block device files\n" "%6d links\n" "%6d symbolic links\n" "------\n" "%6d files\n", regular,directory,chardev,blockdev, links-2*directory+1,symlinks,total-2*directory+1); } if (changed) { write_tables(); printf( "----------------------------\n" "FILE SYSTEM HAS BEEN CHANGED\n" "----------------------------\n"); for (count=0 ; count<3 ; count++) sync(); } else if ( repair ) write_super_block(); if (repair && !automatic) tcsetattr(0,TCSANOW,&termios); if (changed) retcode += 3; if (errors_uncorrected) retcode += 4; return retcode; }
Commit message
This repository is read-only for this account.
Repository snapshot
Current branch
master
Visibility
public
Your access
Read
Remote
Configured
File activity
View file history