Hello community, here is the log from the commit of package parti for openSUSE:Factory checked in at 2017-04-11 09:49:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/parti (Old) and /work/SRC/openSUSE:Factory/.parti.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "parti" Tue Apr 11 09:49:01 2017 rev:3 rq:487027 version:1.14 Changes: -------- --- /work/SRC/openSUSE:Factory/parti/parti.changes 2016-10-18 10:42:55.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.parti.new/parti.changes 2017-04-11 09:49:02.688181230 +0200 @@ -1,0 +2,9 @@ +Mon Apr 3 10:15:14 UTC 2017 - [email protected] + +- update docs a bit +- code de-duplication +- re-arrange fat fs output a bit +- parse vfat super block +- 1.14 + +------------------------------------------------------------------- Old: ---- parti-1.13.tar.xz New: ---- parti-1.14.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ parti.spec ++++++ --- /var/tmp/diff_new_pack.vKLVZp/_old 2017-04-11 09:49:03.388082360 +0200 +++ /var/tmp/diff_new_pack.vKLVZp/_new 2017-04-11 09:49:03.392081795 +0200 @@ -18,7 +18,7 @@ Name: parti -Version: 1.13 +Version: 1.14 Release: 0 Summary: Show partition table information License: GPL-3.0 ++++++ parti-1.13.tar.xz -> parti-1.14.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-1.13/README.md new/parti-1.14/README.md --- old/parti-1.13/README.md 2016-10-14 14:21:31.000000000 +0200 +++ new/parti-1.14/README.md 2017-04-03 12:10:59.000000000 +0200 @@ -2,17 +2,19 @@ ## About -`parti` shows partition table information for +`parti` shows partition and file system details for * [Master Boot Record (MBR) Partition Table][mbr] * [GUID Partition Table (GPT)][gpt] * [Apple Partition Map][apm] * [El Torito Bootable CD/DVD][eltorito] +* [FAT file system BPB][fat] [mbr]: https://en.wikipedia.org/wiki/Master_boot_record [gpt]: https://en.wikipedia.org/wiki/GUID_Partition_Table [apm]: https://en.wikipedia.org/wiki/Apple_Partition_Map [eltorito]: https://en.wikipedia.org/wiki/El_Torito_%28CD-ROM_standard%29 +[fat]: https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#BPB It shows the complete information but mostly in uninterpreted form (unlike partitioning tools like `fdisk` or `parted`). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-1.13/VERSION new/parti-1.14/VERSION --- old/parti-1.13/VERSION 2016-10-14 14:21:31.000000000 +0200 +++ new/parti-1.14/VERSION 2017-04-03 12:10:59.000000000 +0200 @@ -1 +1 @@ -1.13 +1.14 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-1.13/changelog new/parti-1.14/changelog --- old/parti-1.13/changelog 2016-10-14 14:21:31.000000000 +0200 +++ new/parti-1.14/changelog 2017-04-03 12:10:59.000000000 +0200 @@ -1,3 +1,9 @@ +2017-03-31: 1.14 + - update docs a bit + - code de-duplication + - re-arrange fat fs output a bit + - parse vfat super block + 2015-10-12: 1.13 - show decoded gpt attribute bits diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-1.13/parti.c new/parti-1.14/parti.c --- old/parti-1.13/parti.c 2016-10-14 14:21:31.000000000 +0200 +++ new/parti-1.14/parti.c 2017-04-03 12:10:59.000000000 +0200 @@ -184,6 +184,9 @@ int fs_probe(uint64_t offset); void dump_zipl_components(uint64_t sec); void dump_zipl(void); +int fs_detail_fat(int indent, uint64_t sector); +int fs_detail(int indent, uint64_t sector); +void disk_detail(void); struct option options[] = { @@ -263,6 +266,8 @@ return 3; } + disk_detail(); + fs_detail(0, 0); dump_mbr_ptable(); dump_gpt_ptables(); dump_apple_ptables(); @@ -472,7 +477,14 @@ memcpy(name, buf, len); name[len] = 0; - for(n = name, i = len - 1; i > 0 && !n[i]; i--); + for(n = name, i = len - 1; i >= 0; i--) { + if(n[i] == 0 || n[i] == 0x20 || n[i] == 0x09 || n[i] == 0x0a) { + n[i] = 0; + } + else { + break; + } + } return name; } @@ -652,19 +664,11 @@ if(opt.show.raw && ptable->base) printf(", ext base %+d", ptable->base); printf("\n"); - fs_probe(((unsigned long long) ptable->start.lin + ptable->base) * opt.disk.block_size); printf(" type 0x%02x", ptable->type); char *s = mbr_partition_type(ptable->type); if(s) printf(" (%s)", s); - if(fs.type) { - printf(", fs \"%s\"", fs.type); - if(fs.label) printf(", label \"%s\"", fs.label); - if(fs.uuid) printf(", uuid \"%s\"", fs.uuid); - } - if((s = iso_block_to_name((unsigned long long) ptable->start.lin + ptable->base))) { - printf(", \"%s\"", s); - } printf("\n"); + fs_detail(7, (unsigned long long) ptable->start.lin + ptable->base); } } @@ -700,6 +704,13 @@ return; } + for(i = j = 0; i < 4 * 16; i++) { + j |= read_byte(buf + 0x1be + i); + } + + // empty partition table + if(!j) return; + parse_ptable(buf, 0x1be, ptable, 0, 0, 4); i = guess_geo(ptable, 4, &s, &h); if(!i) { @@ -715,8 +726,6 @@ opt.disk.size = ul >> 9; opt.disk.cylinders = opt.disk.size / (opt.disk.sectors * opt.disk.heads); - printf("%s: %llu sectors\n", opt.disk.name, (unsigned long long) opt.disk.size); - id = read_dword_le(buf + 0x1b8); printf(SEP "\nmbr id: 0x%08x\n", id); @@ -892,18 +901,8 @@ // actually it's utf16le, but really... printf("%s", utf32_to_utf8(htole32(le16toh(*n)))); } - printf("\""); - - fs_probe((unsigned long long) le64toh(p->first_lba) * opt.disk.block_size); - printf(", fs \"%s\"", fs.type ?: "unknown"); - if(fs.label) printf(", label \"%s\"", fs.label); - if(fs.uuid) printf(", uuid \"%s\"", fs.uuid); - - if((s = iso_block_to_name(le64toh(p->first_lba)))) { - printf(", \"%s\"", s); - } + printf("\"\n"); - printf("\n"); if(opt.show.raw) { printf(" name_hex[%d]", name_len); n = p->name; @@ -913,6 +912,7 @@ printf("\n"); } + fs_detail(7, le64toh(p->first_lba)); } free(part0); @@ -1057,6 +1057,8 @@ s = cname(apple->name, sizeof apple->name); printf(" name[%d] \"%s\"\n", (int) strlen(s), s); + + fs_detail(5, be32toh(apple->start)); } return 1; @@ -1147,14 +1149,9 @@ if((s = iso_block_to_name(le32toh(el->entry.start) << 2))) { printf(", \"%s\"", s); } - if(fs_probe((unsigned long long) le32toh(el->entry.start) * opt.disk.block_size)) { - printf(", fs \"%s\"", fs.type); - if(fs.label) printf(", label \"%s\"", fs.label); - if(fs.uuid) printf(", uuid \"%s\"", fs.uuid); - } - printf("\n"); s = cname(el->entry.name, sizeof el->entry.name); - printf(" selection criteria 0x%02x \"%s\"\n", el->entry.criteria, s); + printf("\n selection criteria 0x%02x \"%s\"\n", el->entry.criteria, s); + fs_detail(7, le32toh(el->entry.start)); break; case 0x90: @@ -1292,7 +1289,6 @@ fs.uuid = strdup(data); } } - } blkid_free_probe(pr); @@ -1474,3 +1470,188 @@ } } + +/* + * Print fat file system details. + * + * The fs starts at sector (sector size is opt.disk.block_size). + * The output is indented by 'indent' spaces. + * If indent is 0, prints also a separator line. + */ +int fs_detail_fat(int indent, uint64_t sector) +{ + unsigned char buf[opt.disk.block_size]; + int i; + unsigned bpb_len, fat_bits, bpb32; + unsigned bytes_p_sec, sec_p_cluster, resvd_sec, fats, root_ents, sectors; + unsigned hidden, fat_secs, data_start, clusters, root_secs; + unsigned drv_num; + + if(opt.disk.block_size < 0x200) return 0; + + i = disk_read(buf, sector, 1); + + if(i || read_word_le(buf + 0x1fe) != 0xaa55) return 0; + + if(read_byte(buf) == 0xeb) { + i = 2 + (int8_t) read_byte(buf + 1); + } + else if(read_byte(buf) == 0xe9) { + i = 3 + (int16_t) read_word_le(buf + 1); + } + else { + i = 0; + } + + if(i < 3) return 0; + + bpb_len = i; + + if(!strcmp(cname(buf + 3, 8), "NTFS")) return 0; + + bytes_p_sec = read_word_le(buf + 11); + sec_p_cluster = read_byte(buf + 13); + resvd_sec = read_word_le(buf + 14); + fats = read_byte(buf + 16); + root_ents = read_word_le(buf + 17); + sectors = read_word_le(buf + 19); + hidden = read_dword_le(buf + 28); + if(!sectors) sectors = read_dword_le(buf + 32); + fat_secs = read_word_le(buf + 22); + bpb32 = fat_secs ? 0 : 1; + if(bpb32) fat_secs = read_dword_le(buf + 36); + + if(!sec_p_cluster || !fats) return 0; + + // bytes_p_sec should be a power of 2 and > 0 + if(!bytes_p_sec || (bytes_p_sec & (bytes_p_sec - 1))) return 0; + + root_secs = (root_ents * 32 + bytes_p_sec - 1 ) / bytes_p_sec; + + data_start = resvd_sec + fats * fat_secs + root_secs; + + clusters = (sectors - data_start) / sec_p_cluster; + + fat_bits = 12; + if(clusters >= 4085) fat_bits = 16; + if(clusters >= 65525) fat_bits = 32; + + drv_num = read_byte(buf + (bpb32 ? 64 : 36)); + + if(indent == 0) printf(SEP "\n"); + + printf("%*sfat%u:\n", indent, "", fat_bits); + + indent += 2; + + printf("%*ssector size: %u\n", indent, "", bytes_p_sec); + + printf( + "%*sbpb[%u], oem \"%s\", media 0x%02x, drive 0x%02x, hs %u/%u\n", indent, "", + bpb_len, + cname(buf + 3, 8), + read_byte(buf + 21), + drv_num, + read_word_le(buf + 26), + read_word_le(buf + 24) + ); + + if(read_byte(buf + (bpb32 ? 66 : 38)) == 0x29) { + printf("%*svol id 0x%08x, label \"%s\"", indent, "", + read_dword_le(buf + (bpb32 ? 67 : 39)), + cname(buf + (bpb32 ? 71 : 43), 11) + ); + printf(", fs type \"%s\"\n", cname(buf + (bpb32 ? 82 : 54), 8)); + } + + if(bpb32) { + printf("%*sextflags 0x%02x, fs ver %u.%u, fs info %u, backup bpb %u\n", indent, "", + read_byte(buf + 40), + read_byte(buf + 43), read_byte(buf + 42), + read_word_le(buf + 48), + read_word_le(buf + 50) + ); + } + + printf("%*sfs size %u, hidden %u, data start %u\n", indent, "", + sectors, + hidden, + data_start + ); + + printf("%*scluster size %u, clusters %u\n", indent, "", + sec_p_cluster, + clusters + ); + + printf("%*sfats %u, fat size %u, fat start %u\n", indent, "", + fats, + fat_secs, + resvd_sec + ); + + if(bpb32) { + printf("%*sroot cluster %u\n", indent, "", + read_dword_le(buf + 44) + ); + } + else { + printf("%*sroot entries %u, root size %u, root start %u\n", indent, "", + root_ents, + root_secs, + resvd_sec + fats * fat_secs + ); + } + + return 1; +} + + +/* + * Print file system details. + * + * The fs starts at sector (sector size is opt.disk.block_size). + * The output is indented by 'indent' spaces. + * If indent is 0, prints also a separator line. + */ +int fs_detail(int indent, uint64_t sector) +{ + char *s; + int fs_ok = fs_probe(sector * opt.disk.block_size); + + if(!fs_ok) return fs_ok; + + if(indent == 0) { + printf(SEP "\nfile system:\n"); + indent += 2; + } + + printf("%*sfs \"%s\"", indent, "", fs.type); + if(fs.label) printf(", label \"%s\"", fs.label); + if(fs.uuid) printf(", uuid \"%s\"", fs.uuid); + + if((s = iso_block_to_name((sector * opt.disk.block_size) >> 9))) { + printf(", \"%s\"", s); + } + printf("\n"); + + fs_detail_fat(indent, sector); + + return fs_ok; +} + + +/* + * Print file name and size. + */ +void disk_detail() +{ + struct stat sbuf; + uint64_t ul = 0; + + if(!fstat(opt.disk.fd, &sbuf)) ul = sbuf.st_size; + if(!ul && ioctl(opt.disk.fd, BLKGETSIZE64, &ul)) ul = 0; + + printf("%s: %llu sectors\n", opt.disk.name, (unsigned long long) ul >> 9); +} +
