📄 badblo~1.c
字号:
/* badblocks - collect bad blocks in a file Author: Jacob Bunschoten *//* Usage "badblocks block_special [Up_to_7_blocks]" *//* This program is written to handle BADBLOCKS on a hard or floppy disk. * The program asks for block_numbers. These numbers can be obtained with * the program readall, written by A. Tanenbaum. It then creates a * file on the disk containing up to 7 bad blocks. * * BUG: * * When the zone_size > block_size it can happen that * the zone is already allocated. This means some * file is using this zone and may use all the blocks including * the bad one. This can be cured by inspecting the zone_bitmap * (is already done) and change the file if this zone is used. * This means that another zone must be allocated and * the inode wich claims this zone must be found and changed. * */#include <sys/types.h>#include <sys/stat.h>#include <minix/config.h>#include <minix/type.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include "../../fs/const.h" /* must be included before stdio.h */#undef printf /* so its define of printf can be undone */#include "../../fs/type.h"#include <string.h>#include <stdio.h>_PROTOTYPE(int main, (int argc, char **argv));_PROTOTYPE(void rw_super, (int flag));_PROTOTYPE(void get_super, (void));_PROTOTYPE(void put_super, (void));_PROTOTYPE(void rw_inode, (struct stat * stat_ptr, int rw_mode));_PROTOTYPE(void get_inode, (struct stat * stat_ptr));_PROTOTYPE(void put_inode, (struct stat * stat_ptr));_PROTOTYPE(long rd_cmdline, (int argc, char *argv[]));_PROTOTYPE(void modify, (int nr_blocks));_PROTOTYPE(void save_blk, (block_t blk_num));_PROTOTYPE(void reset_blks, (void));_PROTOTYPE(void show_blks, (void));_PROTOTYPE(int blk_is_used, (block_t blk_num));_PROTOTYPE(int blk_ok, (block_t num));_PROTOTYPE(void set_bit, (zone_t num));_PROTOTYPE(long rd_num, (void));_PROTOTYPE(int ok, (char *str));_PROTOTYPE(void done, (int nr));/* Super block table. * * The disk layout is: * * Item # block * boot block 1 * super block 1 * inode map s_imap_blocks * zone map s_zmap_blocks * inodes (s_ninodes + 1 + inodes_per_block - 1)/inodes_per_block * unused * data zones (s_nzones - s_firstdatazone) << s_log_zone_size * */#define OK 0#define NOT_OK 1#define QUIT 2#define READ 0#define WRITE 1#define HARMLESS 0#define DIR_CREATED 1#define DEV_MOUNTED 2#define FILE_EXISTS 3#define SUCCESS 4#define BYTE 0377#define BLOCK_SIZE 1024#define SIZE_OF_INT (sizeof (int) )/* Define V_NR_DZONES as the larger of V1_NR_DZONES and V2_NR_DZONES. */#if (V1_NR_DZONES > V2_NR_DZONES)#define V_NR_DZONES V1_NR_DZONES#define V_SMALLER V2_NR_DZONES#else#define V_NR_DZONES V2_NR_DZONES#define V_SMALLER V1_NR_DZONES#endifstruct super_block { ino_t s_ninodes; /* # usable inodes on the minor device */ zone1_t s_nzones; /* total device size, including bit maps etc */ short s_imap_blocks; /* # of blocks used by inode bit map */ short s_zmap_blocks; /* # of blocks used by zone bit map */ zone1_t s_firstdatazone; /* number of first data zone */ short s_log_zone_size; /* log2 of blocks/zone */ off_t s_max_size; /* maximum file size on this device */ short s_magic; /* magic number to recognize super-blocks */ short s_pad; /* try to avoid compiler-dependent padding */ zone_t s_zones; /* number of zones (replaces s_nzones in V2) */} super_block; /* ====== globals ======= */char *dev_name;char f_name[] = ".Bad_XXXXXX";char file_name[50];char dir_name[] = "/tmpXXXXXX";block_t block[V_NR_DZONES + 1]; /* last block contains zero */int interactive; /* 1 if interactive (argc == 2) */int position = 2; /* next block # is argv[position] */FILE *f;int fd;int eofseen; /* set if '\n' seen */struct stat stat_buf;struct super_block *sp;int inodes_per_block;size_t inode_size;int v1fs; /* TRUE for V1 file system, FALSE for V2 */d1_inode d1inode; /* declare a V1 disk inode */d1_inode *ip1;d2_inode d2inode; /* declare a V2 disk inode */d2_inode *ip2; /* ====== super block routines ======= */void rw_super(flag)int flag;{ /* read or write a superblock */ int rwd; lseek(fd, 0L, SEEK_SET); /* rewind */ lseek(fd, (long) BLOCK_SIZE, SEEK_SET); /* seek */ if (flag == READ) rwd = read(fd, (char *) sp, SUPER_SIZE); else rwd = write(fd, (char *) sp, SUPER_SIZE); if (rwd != SUPER_SIZE) { /* ok ? */ printf("Bad %s in get_super() (should be %u is %d)\n", flag == READ ? "read" : "write", (unsigned) SUPER_SIZE, rwd); done(DIR_CREATED); }}void get_super() /* Get super_block. global pointer sp is used */{ rw_super(READ); if (sp->s_magic == SUPER_MAGIC) { /* This is a V1 file system. */ v1fs = 1; /* file system is not V2 */ } else if (sp->s_magic == SUPER_V2) { /* This is a V2 file system. */ v1fs = 0; /* this is a V2 file system */ } else { /* Neither V1 nor V2. */ printf("Bad magic number in super_block (0x%x)\n", (unsigned) sp->s_magic); done(DIR_CREATED); }}void put_super(){ rw_super(WRITE);} /* ========== inode routines =========== */void rw_inode(stat_ptr, rw_mode)struct stat *stat_ptr;int rw_mode;{ int rwd; ino_t i_num; block_t blk, offset; i_num = stat_ptr->st_ino; blk = (block_t) (2 + sp->s_imap_blocks + sp->s_zmap_blocks); blk += (block_t) ((i_num - 1) / inodes_per_block); blk *= (block_t) (BLOCK_SIZE);/* this block */ offset = (block_t) ((i_num - 1) % inodes_per_block); offset *= (block_t) (inode_size); /* and this offset */ lseek(fd, (off_t) 0, SEEK_SET); /* rewind */ lseek(fd, (off_t) (blk + offset), SEEK_SET); /* seek */ /* Pointer is at the inode */ if (v1fs) { /* This is a V1 file system. */ if (rw_mode == READ) { /* read it */ rwd = read(fd, (char *) ip1, inode_size); } else { /* write it */ rwd = write(fd, (char *) ip1, inode_size); } } else { /* This is a V2 file system. */ if (rw_mode == READ) { /* read it */ rwd = read(fd, (char *) ip2, inode_size); } else { /* write it */ rwd = write(fd, (char *) ip2, inode_size); } } if (rwd != inode_size) { /* ok ? */ printf("Bad %s in get_inode()\n", (rw_mode == READ) ? "read" : "write"); done(DIR_CREATED); }}void get_inode(stat_ptr)struct stat *stat_ptr;{ int cnt; rw_inode(stat_ptr, READ); if (v1fs) { for (cnt = 0; cnt < V1_NR_TZONES; cnt++) ip1->d1_zone[cnt] = 0; /* Just to be safe */ } else { for (cnt = 0; cnt < V2_NR_TZONES; cnt++) ip2->d2_zone[cnt] = 0; /* Just to be safe */ }}void put_inode(stat_ptr)struct stat *stat_ptr;{ rw_inode(stat_ptr, WRITE);} /* ============== main program ================= */int main(argc, argv)int argc;char *argv[];{ int cnt, finished; block_t blk_nr; struct stat dev_stat; FILE *fp; sp = &super_block; ip1 = &d1inode; ip2 = &d2inode; if (argc < 2 || argc > 9) { fprintf(stderr, "Usage: %s block_special [up_to_7_blocks]\n", argv[0]); done(HARMLESS); } interactive = (argc == 2 ? 1 : 0); /* Do some test. */ if (geteuid()) { printf("Sorry, not in superuser mode \n"); printf("Set_uid bit must be on or you must become super_user\n"); done(HARMLESS); } dev_name = argv[1]; mktemp(dir_name); if (mkdir(dir_name, 0777) == -1) { fprintf(stderr, "%s is already used in system\n", dir_name); done(HARMLESS); } /* Mount device. This call may fail. */ mount(dev_name, dir_name, 0); /* Succes. dev was mounted, try to umount */ /* Umount device. Playing with the file system while other processes * have access to this device is asking for trouble */ if (umount(dev_name) == -1) { printf("Could not umount device %s.\n", dev_name); done(HARMLESS); } mktemp(f_name); /* Create "/tmpXXXXpid/.BadXXpid" */ strcat(file_name, dir_name); strcat(file_name, "/"); strcat(file_name, f_name); if (mount(dev_name, dir_name, 0) == -1) { /* this call should work */ fprintf(stderr, "Could not mount device anymore\n"); done(HARMLESS); } if (stat(file_name, &stat_buf) != -1) { printf("File %s already exists\n", file_name); done(DEV_MOUNTED); } if ((fp = fopen(file_name, "w")) == NULL) { printf("Cannot create file %s\n", file_name); done(DEV_MOUNTED); } chmod(file_name, 0); /* "useless" file */ if (stat(file_name, &stat_buf) == -1) { printf("What? Second call from stat failed\n"); done(FILE_EXISTS); } /* Stat buf must be safed. We can now calculate the inode on disk */ fclose(fp); /* ===== the badblock file is created ===== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -