📄 swapfs.c
字号:
if (write(1, buf, BLOCK_SIZE) != BLOCK_SIZE) fail("write failed on output file");}static int convcpy(dst, src, format)char *dst;char *src;int *format;{ char *old_src = src; register char tmp; int i; for (i = 0; format[i] > 0; i++) { switch (format[i]) { case 1: *dst++ = *src++; break; case 2: tmp = *src++; *dst++ = *src++; *dst++ = tmp; break; case 4: tmp = src[0]; dst[0] = src[3]; dst[3] = tmp; tmp = src[1]; dst[1] = src[2]; dst[2] = tmp; src += 4; dst += 4; break; default: fail("wrong format array for convcpy"); } } return(src - old_src);}static void conv2_blkcpy(dst, src)char *dst;char *src;{ int i; register char tmp; for (i = 0; i < BLOCK_SIZE; i += 2) { tmp = *src++; *dst++ = *src++; *dst++ = tmp; }}static void conv4_blkcpy(dst, src)char *dst;char *src;{ int i; register char tmp; for (i = 0; i < BLOCK_SIZE; i += 4) { tmp = src[0]; dst[0] = src[3]; dst[3] = tmp; tmp = src[1]; dst[1] = src[2]; dst[2] = tmp; src += 4; dst += 4; }}static void conv2cpy(dst, src)char *dst;char *src;{ register char tmp; tmp = *src++; *dst++ = *src++; *dst++ = tmp;}static int inode_size(version)int version;{ return(version == 1) ? V1_INODE_SIZE : V2_INODE_SIZE;}static void init_super(sp, buf)super_t *sp;char *buf;{ int magic; long imapblks, zmapblks; big_endian_fs = 0; /* guess the file system is little endian */ magic = two_bytes(buf + MAGIC_OFFSET); if (magic != V1_MAGIC && magic != V2_MAGIC) { big_endian_fs = 1; magic = two_bytes(buf + MAGIC_OFFSET); } switch (magic) { case V1_MAGIC: sp->version = 1; break; case V2_MAGIC: sp->version = 2; break; default: fail("Not a Minix file system");} if (verbose_flag) fprintf(stderr, "\nVersion = V%d, %s endian.\n", sp->version, big_endian_fs ? "big" : "little"); sp->ninodes = two_bytes(buf + NINODES_OFFSET); imapblks = two_bytes(buf + IMAP_BLOCKS_OFFSET); sp->imap_blocks = imapblks; zmapblks = two_bytes(buf + ZMAP_BLOCKS_OFFSET); sp->zmap_blocks = zmapblks; sp->firstdatazone = two_bytes(buf + FIRSTDATAZONE_OFFSET); sp->log_zone_size = two_bytes(buf + LOG_ZONE_SIZE_OFFSET); if (sp->version == 1) sp->zones = two_bytes(buf + V1_ZONES_OFFSET); else sp->zones = four_bytes(buf + V2_ZONES_OFFSET); sp->inodes_per_block = BLOCK_SIZE / inode_size(sp->version); if (imapblks < 0 || zmapblks < 0 || sp->ninodes < 1 || sp->zones < 1) fail("Bad superblock"); if (sp->log_zone_size != 0) fail("Can't swap file systems with different zone and block sizes"); sp->first_imap_block = SUPER_BLOCK_OFF + 1; sp->first_zmap_block = sp->first_imap_block + sp->imap_blocks; sp->first_inode_block = sp->first_zmap_block + sp->zmap_blocks; sp->dzmap_size = sp->zones - sp->firstdatazone; if (verbose_flag) { fprintf(stderr, "nzones = %ld, ", sp->zones); fprintf(stderr, "ninodes = %u, ", sp->ninodes); fprintf(stderr, "first data zone = %ld.\n\n", sp->firstdatazone); }}static void get_inode(ip, buf, version)inode_t *ip;char *buf;int version;{ int i; int mode; if (version == 1) { mode = two_bytes(buf + INODE1_MODE_OFF); ip->size = four_bytes(buf + INODE1_SIZE_OFF); ip->ind1 = two_bytes(buf + INODE1_IND1_OFF); ip->ind2 = two_bytes(buf + INODE1_IND2_OFF); ip->ind3 = 0; for (i = 0; i < NR_DIRECT_ZONES; i++) ip->direct[i] = two_bytes(buf + INODE1_DIRECT_OFF + 2 * i); } else { mode = two_bytes(buf + INODE2_MODE_OFF); ip->size = four_bytes(buf + INODE2_SIZE_OFF); ip->ind1 = four_bytes(buf + INODE2_IND1_OFF); ip->ind2 = four_bytes(buf + INODE2_IND2_OFF); ip->ind3 = four_bytes(buf + INODE2_IND3_OFF); for (i = 0; i < NR_DIRECT_ZONES; i++) ip->direct[i] = four_bytes(buf + INODE2_DIRECT_OFF + 4 * i); } if (mode == 0) { if (ip->size % DIR_ENTRY_SIZE == 0) ip->ztype = T_MAYBE_OLD_DIR; else ip->ztype = T_OLD_NON_DIR; if (was_blk_special(*ip)) ip->size = 0; } else { mode = mode & INODE_MODE_MASK; if (mode == INODE_BLK_SPECIAL_MODE || mode == INODE_CHR_SPECIAL_MODE) ip->size = 0; /* prevent the use of the block numbers. */ ip->ztype = (mode == INODE_DIR_MODE) ? T_DIR : T_NON_DIR; }}static int check_inode(inode, super)inode_t inode;super_t super;{ int i; for (i = 0; i < NR_DIRECT_ZONES; i++) if (!check_blk_number(inode.direct[i], super)) return 0; return(check_blk_number(inode.ind1, super) && check_blk_number(inode.ind2, super) && check_blk_number(inode.ind3, super));}static int check_blk_number(num, super)blockn_t num;super_t super;{ if (num == 0 || (num >= super.firstdatazone && num < super.zones)) return 1; fprintf(stderr, "warning bad block number %ld in inode.\n", num); return 0;}static int was_blk_special(inode)inode_t inode;{ int i, result; blockn_t block_size; if (inode.size % BLOCK_SIZE || inode.ind1) return 0; block_size = inode.size / BLOCK_SIZE; for (i = NR_DIRECT_ZONES - 1; i >= 0; i--) if (inode.direct[i] != 0) break; result = (i < 1 && block_size > i + 1); if (debug_flag && result) { fprintf(stderr, "old block special file detected (slot = %d).\n", i); } return result;}static void cw_inode_block(buf, ninodes, version)char *buf;inodesn_t ninodes;int version;{ char output_buf[BLOCK_SIZE]; char *src, *dst; inodesn_t i; int cnt, free_bytes; int *format; src = buf; dst = output_buf; format = (version == 1) ? inode1_format : inode2_format; for (i = 0; i < ninodes; i++) { cnt = convcpy(dst, src, format); src += cnt; dst += cnt; } assert(cnt == inode_size(version)); free_bytes = BLOCK_SIZE - (src - buf); assert(free_bytes >= 0); if (verbose_flag && free_bytes > 0) { /* There is a small change that the last free inode has no * matching bit in the last inode bit map block: e.g. if * sp->ninodes == 8191. */ fprintf(stderr, "%5d bytes (%d inodes) free in last inode block.\n", free_bytes, free_bytes / inode_size(version)); memcpy(dst, src, (size_t) free_bytes); } write_block(output_buf);}static void proc_ind(dzmap, curr_ind, buf, super)dzmap_t dzmap;size_t curr_ind;char *buf;super_t super;{ int indnum, i, ztype; int word_size; /* size of zone block number in ind. block in * bytes */ unsigned char dz, tmp_dz; blockn_t blk, ind_blk; int bad_range = 0, hidden_zero = 0, zero_flag = 0, expired = 0; size_t blk_index; dz = dzmap[curr_ind]; indnum = dz & INDIRECT_MASK; ztype = dz & T_MASK; ind_blk = curr_ind + super.firstdatazone; word_size = (super.version == 1) ? 2 : 4; assert(indnum > 0); for (i = 0; i < BLOCK_SIZE; i += word_size) { if (word_size == 2) blk = two_bytes(buf + i); else blk = four_bytes(buf + i); if (blk == 0) zero_flag = 1; else if (blk < super.firstdatazone || blk >= super.zones) bad_range = 1; else { if (zero_flag) hidden_zero = 1; blk_index = blk - super.firstdatazone; tmp_dz = dzmap[blk_index]; if (ztype_class(tmp_dz & T_MASK) == In_use_zone) expired = 1; } } if (ztype_class(ztype) == In_use_zone) { if (bad_range) { fprintf(stderr, "%s zone block contains ", ind_str[indnum]); fail("illegal value"); } if ((ztype == T_DIR || indnum > 1) && hidden_zero) { fprintf(stderr, "WARNING: %s zone block %ld contains ", ind_str[indnum], ind_blk); fprintf(stderr, "unexpected zero block numbers\n"); } } else { if (expired) { dzmap[curr_ind] &= ~(INDIRECT_MASK & IND_CONFLICT_BIT); return; } /* Not yet implemented. :-( if (bad_range || (indnum > 1 && * hidden_zero) || equal_values(buf, super.version ) { } */ } for (i = 0; i < BLOCK_SIZE; i += word_size) { if (word_size == 2) blk = two_bytes(buf + i); else blk = four_bytes(buf + i); if (blk == 0) continue; blk_index = blk - super.firstdatazone; tmp_dz = dzmap[blk_index]; if (ztype_class(tmp_dz & T_MASK) == In_use_zone) { /* trouble */ if ((tmp_dz & INDIRECT_MASK) == indnum - 1 && (tmp_dz & T_MASK) == ztype) fprintf(stderr, "WARNING: %s zone block %ld used more \than once\n", ind_str[indnum - 1], blk); else { fprintf(stderr, "Block %ld used more than ", blk); fail("once with different types"); } } dzmap[blk_index] = (dz & ~INDIRECT_MASK) | (indnum - 1); } dzmap[curr_ind] |= IND_PROCESSED_BIT;}static void cw_dir_block(buf)char *buf;{ char output_buf[BLOCK_SIZE]; int ino, i, old_ino_offset; memcpy(output_buf, buf, BLOCK_SIZE); for (i = 0; i < BLOCK_SIZE; i += DIR_ENTRY_SIZE) { ino = two_bytes(buf + i); if (ino == 0) { old_ino_offset = i + DIR_ENTRY_SIZE - 2; conv2cpy(output_buf + old_ino_offset, buf + old_ino_offset); } else conv2cpy(output_buf + i, buf + i); } write_block(output_buf);}static void dzmap_add_inode(dzmap, inode, super)dzmap_t dzmap;inode_t inode;super_t super;{ int i; if (inode.size == 0 || !check_inode(inode, super)) return; for (i = 0; i < NR_DIRECT_ZONES; i++) dz_update(dzmap, inode.direct[i], 0, inode.ztype, super); dz_update(dzmap, inode.ind1, 1, inode.ztype, super); dz_update(dzmap, inode.ind2, 2, inode.ztype, super); dz_update(dzmap, inode.ind3, 3, inode.ztype, super);}static void dz_update(dzmap, blknum, new_indnum, new_ztype, super)dzmap_t dzmap;blockn_t blknum;int new_indnum;int new_ztype;super_t super;{ size_t dznum; int old_indnum; int old_ztype; unsigned char *dz; char new_dz; if (blknum == 0) return; dznum = (size_t) (blknum - super.firstdatazone); dz = &dzmap[dznum]; old_indnum = *dz & INDIRECT_MASK; old_ztype = *dz & T_MASK; new_dz = new_ztype | new_indnum; if (ztype_class(new_ztype) > ztype_class(old_ztype)) { *dz = new_dz; return; } else if (ztype_class(new_ztype) < ztype_class(old_ztype)) return; /* Collision: old and new have the same class */ if (ztype_class(old_ztype) == In_use_zone) { /* trouble */ if (new_indnum == old_indnum && new_ztype == old_ztype) { fprintf(stderr, "WARNING: file system corrupt, zone block %ld \is used more than once.\n", blknum); return; } fprintf(stderr, "ERROR: file system corrupt, zone block %ld is used \more than once.\n", blknum); fail("Can't determine its type"); } assert(ztype_class(old_ztype) == Old_zone); if (new_indnum != old_indnum) { *dz |= IND_CONFLICT_BIT; if (new_indnum > old_indnum) { *dz &= ~INDIRECT_MASK; *dz |= new_indnum; } } if (new_ztype == T_MAYBE_OLD_DIR || old_ztype == T_MAYBE_OLD_DIR) { *dz |= TYPE_CONFLICT_BIT; *dz &= ~T_MASK; *dz |= T_MAYBE_OLD_DIR; }}static class_t ztype_class(ztype)int ztype;{ class_t class; if (ztype == T_MAYBE_OLD_DIR || ztype == T_OLD_NON_DIR) class = Old_zone; else if (ztype == T_DIR || ztype == T_NON_DIR) class = In_use_zone; else class = Unused_zone; return class;}static void fail(str)char *str;{ fprintf(stderr, "%s\n", str); exit(1);}static unsigned int two_bytes(buf)char buf[2];{ unsigned char *ubuf = (unsigned char *) buf; if (big_endian_fs) return(ubuf[0] << 8) | ubuf[1]; else return(ubuf[1] << 8) | ubuf[0];}static long four_bytes(buf)char buf[4];{ unsigned char *ubuf = (unsigned char *) buf; register int r1, r2; if (big_endian_fs) { r1 = (ubuf[0] << 8) | ubuf[1]; r2 = (ubuf[2] << 8) | ubuf[3]; } else { r2 = (ubuf[1] << 8) | ubuf[0]; r1 = (ubuf[3] << 8) | ubuf[2]; } return((long) r1 << 16) | r2;}static void usage(arg0)char *arg0;{ fprintf(stderr, "usage: %s [-v] srcfs [destfs]\n", arg0); exit(2);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -