📄 ntfsresize.c
字号:
if (resize->prog && resize->prog->cancel) { free(bm); return (0); } if (a->size <= pos) goto done; if (a->bm[pos] == bm[i]) continue; for (cl = pos * 8; cl < (pos + 1) * 8; cl++) { char bit; bit = ntfs_bit_get(a->bm, cl); if (bit == ntfs_bit_get(bm, i * 8 + cl % 8)) continue; if (!mismatch && !bit && !backup_boot && cl == vol->nr_clusters / 2) { /* FIXME: call also boot sector check */ backup_boot = 1; progress_message(resize, "Found backup boot sector in " "the middle of the volume."); continue; } if (++mismatch > 10) continue; progress_message(resize, "Cluster accounting failed at %lld " "(0x%llx): %s cluster in " "$Bitmap", (long long)cl, (unsigned long long)cl, bit ? "missing" : "extra"); } } }done: free(bm); if (mismatch) { err_printf(resize, "Filesystem check failed! Total of %d " "cluster accounting mismatches.", mismatch); err_printf(resize, "%s", corrupt_volume_msg); return (-1); } return (0);}#ifndef __VISOPSYS__/** * progress_init * * Create and scale our progress bar. */static void progress_init(struct progress_bar *p, u64 start, u64 stop, int flags){ p->start = start; p->stop = stop; p->unit = 100.0 / (stop - start); p->resolution = 100; p->flags = flags;}/** * progress_update * * Update the progress bar and tell the user. */static void progress_update(struct progress_bar *p, u64 current){ float percent; if (!(p->flags & NTFS_PROGBAR)) return; if (p->flags & NTFS_PROGBAR_SUPPRESS) return; /* WARNING: don't modify the texts, external tools grep for them */ percent = p->unit * current; if (current != p->stop) { if ((current - p->start) % p->resolution) return; printf("%6.2f percent completed\r", percent); } else printf("100.00 percent completed\n"); fflush(stdout);}#endif /* __VISOPSYS__ */static int inode_close(ntfs_resize_t *resize, ntfs_inode *ni){ if (ntfs_inode_close(ni)) { err_printf(resize, "ntfs_inode_close for inode %llu failed", (unsigned long long)ni->mft_no); return -1; } return 0;}/** * walk_inodes * * Read each record in the MFT, skipping the unused ones, and build up a bitmap * from all the non-resident attributes. */static int build_allocation_bitmap(ntfs_resize_t *resize, ntfs_volume *vol, ntfsck_t *fsck){ s64 nr_mft_records, inode = 0; ntfs_inode *ni; nr_mft_records = vol->mft_na->initialized_size >> vol->mft_record_size_bits; progress_message(resize, "Checking filesystem consistency"); for (; inode < nr_mft_records; inode++) { progress_update(resize->prog, RSZPCNT_CHECK, inode, (nr_mft_records - 1)); if (resize->prog && resize->prog->cancel) return (0); if ((ni = ntfs_inode_open(vol, (MFT_REF)inode)) == NULL) { /* FIXME: continue only if it make sense, e.g. MFT record not in use based on $MFT bitmap */ if (errno == EIO || errno == ENOENT) continue; err_printf(resize, "Reading inode %lld failed", inode); return -1; } if (ni->mrec->base_mft_record) goto close_inode; fsck->ni = ni; if (walk_attributes(resize, vol, fsck) != 0) { inode_close(resize, ni); return -1; }close_inode: if (inode_close(resize, ni) != 0) return -1; } return 0;}static int build_resize_constraints(ntfs_resize_t *resize){ s64 i; runlist *rl; if (!resize->ctx->attr->non_resident) return (0); if (!(rl = ntfs_mapping_pairs_decompress(resize->vol, resize->ctx->attr, NULL))) { err_printf(resize, "ntfs_decompress_mapping_pairs failed"); return (-1); } for (i = 0; rl[i].length; i++) { /* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */ if (rl[i].lcn == LCN_HOLE || rl[i].lcn == LCN_RL_NOT_MAPPED) continue; if (collect_resize_constraints(resize, rl + i) < 0) return (-1); if (resize->shrink) if (collect_relocation_info(resize, rl + i) != 0) return (-1); } free(rl); return (0);}static int resize_constraints_by_attributes(ntfs_resize_t *resize){ if (!(resize->ctx = attr_get_search_ctx(resize, resize->ni, NULL))) return (-1); while (!ntfs_attrs_walk(resize->ctx)) { if (resize->ctx->attr->type == AT_END) break; if (build_resize_constraints(resize) != 0) return (-1); } ntfs_attr_put_search_ctx(resize->ctx); return (0);}static int set_resize_constraints(ntfs_resize_t *resize){ s64 nr_mft_records, inode; ntfs_inode *ni; progress_message(resize, "Collecting resizing constraints"); nr_mft_records = resize->vol->mft_na->initialized_size >> resize->vol->mft_record_size_bits; for (inode = 0; inode < nr_mft_records; inode++) { ni = ntfs_inode_open(resize->vol, (MFT_REF)inode); if (ni == NULL) { if (errno == EIO || errno == ENOENT) continue; err_printf(resize, "Reading inode %lld failed", inode); return (-1); } if (ni->mrec->base_mft_record) goto close_inode; resize->ni = ni; if (resize_constraints_by_attributes(resize) != 0) return (-1);close_inode: if (inode_close(resize, ni) != 0) return (-1); progress_update(resize->prog, RSZPCNT_SETRSZCONST, inode, nr_mft_records); if (resize->prog && resize->prog->cancel) return (0); } return (0);}static int rl_fixup(ntfs_resize_t *resize, runlist **rl){ runlist *tmp = *rl; if (tmp->lcn == LCN_RL_NOT_MAPPED) { s64 unmapped_len = tmp->length; progress_message(resize, "Skip unmapped run at the beginning ..."); if (!tmp->length) { err_printf(resize, "Empty unmapped runlist! Please report!"); return (-1); } (*rl)++; for (tmp = *rl; tmp->length; tmp++) tmp->vcn -= unmapped_len; } for (tmp = *rl; tmp->length; tmp++) { if (tmp->lcn == LCN_RL_NOT_MAPPED) { progress_message(resize, "Skip unmapped run at the end ..."); if (tmp[1].length) { err_printf(resize, "Unmapped runlist in the middle! " "Please report!"); return (-1); } tmp->lcn = LCN_ENOENT; tmp->length = 0; } } return (0);}static int replace_attribute_runlist(ntfs_resize_t *resize, ntfs_volume *vol, ntfs_attr_search_ctx *ctx, runlist *rl){ int mp_size, l; void *mp; ATTR_RECORD *a = ctx->attr; if (rl_fixup(resize, &rl) != 0) return (-1); if ((mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0)) == -1) { err_printf(resize, "ntfs_get_size_for_mapping_pairs failed"); return (-1); } if (a->name_length) { u16 name_offs = le16_to_cpu(a->name_offset); u16 mp_offs = le16_to_cpu(a->mapping_pairs_offset); if (name_offs >= mp_offs) { err_printf(resize, "Attribute name is after mapping pairs! " "Please report!"); return (-1); } } /* CHECKME: don't trust mapping_pairs is always the last item in the attribute, instead check for the real size/space */ l = (int)le32_to_cpu(a->length) - le16_to_cpu(a->mapping_pairs_offset); if (mp_size > l) { s64 remains_size; char *next_attr; progress_message(resize, "Enlarging attribute header ..."); mp_size = (mp_size + 7) & ~7; ntfs_log_verbose("Old mp size : %d\n", l); ntfs_log_verbose("New mp size : %d\n", mp_size); ntfs_log_verbose("Bytes in use : %u\n", (unsigned int) le32_to_cpu(ctx->mrec->bytes_in_use)); next_attr = (char *)a + le16_to_cpu(a->length); l = mp_size - l; ntfs_log_verbose("Bytes in use new : %u\n", l + (unsigned int) le32_to_cpu(ctx->mrec->bytes_in_use)); ntfs_log_verbose("Bytes allocated : %u\n", (unsigned int) le32_to_cpu(ctx->mrec->bytes_allocated)); remains_size = le32_to_cpu(ctx->mrec->bytes_in_use); remains_size -= (next_attr - (char *)ctx->mrec); ntfs_log_verbose("increase : %d\n", l); ntfs_log_verbose("shift : %lld\n", (long long)remains_size); if (le32_to_cpu(ctx->mrec->bytes_in_use) + l > le32_to_cpu(ctx->mrec->bytes_allocated)) { err_printf(resize, "Extended record needed (%u > %u), not yet " "supported! Please try to free less space.", (unsigned int)le32_to_cpu(ctx->mrec-> bytes_in_use) + l, (unsigned int)le32_to_cpu(ctx->mrec-> bytes_allocated)); return (-1); } memmove(next_attr + l, next_attr, remains_size); ctx->mrec->bytes_in_use = cpu_to_le32(l + le32_to_cpu(ctx->mrec->bytes_in_use)); a->length += l; } if (!(mp = calloc(1, mp_size))) { err_printf(resize, "Couldn't get memory"); return (-1); } if (ntfs_mapping_pairs_build(vol, mp, mp_size, rl, 0, NULL)) { err_printf(resize, "ntfs_mapping_pairs_build failed"); return (-1); } memmove((u8*)a + le16_to_cpu(a->mapping_pairs_offset), mp, mp_size); free(mp); return (0);}static void set_bitmap_range(struct bitmap *bm, s64 pos, s64 length, u8 bit){ while (length--) ntfs_bit_set(bm->bm, pos++, bit);}static void set_bitmap_clusters(struct bitmap *bm, runlist *rl, u8 bit){ for (; rl->length; rl++) set_bitmap_range(bm, rl->lcn, rl->length, bit);}static void release_bitmap_clusters(struct bitmap *bm, runlist *rl){ max_free_cluster_range = 0; set_bitmap_clusters(bm, rl, 0);}static void set_max_free_zone(s64 length, s64 end, runlist_element *rle){ if (length > rle->length) { rle->lcn = end - length; rle->length = length; }}static int find_free_cluster(ntfs_resize_t *resize, struct bitmap *bm, runlist_element *rle, s64 nr_vol_clusters, int hint){ /* FIXME: get rid of this 'static' variable */ static s64 pos = 0; s64 i, items = rle->length; s64 free_zone = 0; if (pos >= nr_vol_clusters) pos = 0; if (!max_free_cluster_range) max_free_cluster_range = nr_vol_clusters; rle->lcn = rle->length = 0; if (hint) pos = nr_vol_clusters / 2; i = pos; do { if (!ntfs_bit_get(bm->bm, i)) { if (++free_zone == items) { set_max_free_zone(free_zone, i + 1, rle); break; } } else { set_max_free_zone(free_zone, i, rle); free_zone = 0; } if (++i == nr_vol_clusters) { set_max_free_zone(free_zone, i, rle); i = free_zone = 0; } if (rle->length == max_free_cluster_range) break; } while (i != pos); if (i) set_max_free_zone(free_zone, i, rle); if (!rle->lcn) { errno = ENOSPC; return -1; } if (rle->length < items && rle->length < max_free_cluster_range) { max_free_cluster_range = rle->length; progress_message(resize, "Max free range: %lld", (long long)max_free_cluster_range); } pos = rle->lcn + items; if (pos == nr_vol_clusters) pos = 0; set_bitmap_range(bm, rle->lcn, rle->length, 1); return 0;}static runlist *alloc_cluster(ntfs_resize_t *resize, struct bitmap *bm, s64 items, s64 nr_vol_clusters, int hint){ runlist_element rle; runlist *rl = NULL; int rl_size, runs = 0; s64 vcn = 0; if (items <= 0) { errno = EINVAL; return NULL; } while (items > 0) { if (runs) hint = 0; rle.length = items; if (find_free_cluster(resize, bm, &rle, nr_vol_clusters, hint) == -1) return NULL; rl_size = (runs + 2) * sizeof(runlist_element); if (!(rl = (runlist *)realloc(rl, rl_size))) return NULL; rl_set(rl + runs, vcn, rle.lcn, rle.length); vcn += rle.length; items -= rle.length; runs++; } rl_set(rl + runs, vcn, -1LL, 0LL); return rl;}static int read_all(ntfs_resize_t *resize, struct ntfs_device *dev, void *buf, int count){ int i; while (count > 0) { i = count; if (!NDevReadOnly(dev)) i = dev->d_ops->read(dev, buf, count); if (i < 0) { if (errno != EAGAIN && errno != EINTR) return -1; } else if (i > 0) { count -= i; buf = i + (char *)buf; } else { err_printf(resize, "Unexpected end of file!"); return (-1); } } return 0;}static int write_all(struct ntfs_device *dev, void *buf, int count){ int i; while (count > 0) { i = count; if (!NDevReadOnly(dev)) i = dev->d_ops->write(dev, buf, count); if (i < 0) { if (errno != EAGAIN && errno != EINTR) return -1; } else { count -= i; buf = i + (char *)buf; } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -