Alistair Delva | beaee83 | 2021-02-24 11:27:23 -0800 | [diff] [blame] | 1 | /* Copyright 1997-2003,2006,2007,2009 Alain Knaff. |
| 2 | * This file is part of mtools. |
| 3 | * |
| 4 | * Mtools is free software: you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License as published by |
| 6 | * the Free Software Foundation, either version 3 of the License, or |
| 7 | * (at your option) any later version. |
| 8 | * |
| 9 | * Mtools is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU General Public License |
| 15 | * along with Mtools. If not, see <http://www.gnu.org/licenses/>. |
| 16 | * |
| 17 | * mlabel.c |
| 18 | * Make an MSDOS volume label |
| 19 | */ |
| 20 | |
| 21 | #include "sysincludes.h" |
| 22 | #include "msdos.h" |
| 23 | #include "mainloop.h" |
| 24 | #include "vfat.h" |
| 25 | #include "mtools.h" |
| 26 | #include "nameclash.h" |
| 27 | |
| 28 | static void usage(int ret) NORETURN; |
| 29 | static void usage(int ret) |
| 30 | { |
| 31 | fprintf(stderr, |
| 32 | "Mtools version %s, dated %s\n", mversion, mdate); |
| 33 | fprintf(stderr, |
| 34 | "Usage: %s [-v] drive\n", progname); |
| 35 | exit(ret); |
| 36 | } |
| 37 | |
| 38 | |
| 39 | static void displayInfosector(Stream_t *Stream, union bootsector *boot) |
| 40 | { |
| 41 | InfoSector_t *infosec; |
| 42 | |
| 43 | if(WORD(ext.fat32.infoSector) == MAX16) |
| 44 | return; |
| 45 | |
| 46 | infosec = (InfoSector_t *) safe_malloc(WORD(secsiz)); |
| 47 | force_read(Stream, (char *) infosec, |
| 48 | (mt_off_t) WORD(secsiz) * WORD(ext.fat32.infoSector), |
| 49 | WORD(secsiz)); |
| 50 | printf("\nInfosector:\n"); |
| 51 | printf("signature=0x%08x\n", _DWORD(infosec->signature1)); |
| 52 | if(_DWORD(infosec->count) != MAX32) |
| 53 | printf("free clusters=%u\n", _DWORD(infosec->count)); |
| 54 | if(_DWORD(infosec->pos) != MAX32) |
| 55 | printf("last allocated cluster=%u\n", _DWORD(infosec->pos)); |
| 56 | } |
| 57 | |
| 58 | |
| 59 | static void displayBPB(Stream_t *Stream, union bootsector *boot) { |
| 60 | struct label_blk_t *labelBlock; |
| 61 | |
| 62 | printf("bootsector information\n"); |
| 63 | printf("======================\n"); |
| 64 | printf("banner:\"%.8s\"\n", boot->boot.banner); |
| 65 | printf("sector size: %d bytes\n", WORD(secsiz)); |
| 66 | printf("cluster size: %d sectors\n", boot->boot.clsiz); |
| 67 | printf("reserved (boot) sectors: %d\n", WORD(nrsvsect)); |
| 68 | printf("fats: %d\n", boot->boot.nfat); |
| 69 | printf("max available root directory slots: %d\n", |
| 70 | WORD(dirents)); |
| 71 | printf("small size: %d sectors\n", WORD(psect)); |
| 72 | printf("media descriptor byte: 0x%x\n", boot->boot.descr); |
| 73 | printf("sectors per fat: %d\n", WORD(fatlen)); |
| 74 | printf("sectors per track: %d\n", WORD(nsect)); |
| 75 | printf("heads: %d\n", WORD(nheads)); |
| 76 | printf("hidden sectors: %d\n", DWORD(nhs)); |
| 77 | printf("big size: %d sectors\n", DWORD(bigsect)); |
| 78 | |
| 79 | if(WORD(fatlen)) { |
| 80 | labelBlock = &boot->boot.ext.old.labelBlock; |
| 81 | } else { |
| 82 | labelBlock = &boot->boot.ext.fat32.labelBlock; |
| 83 | } |
| 84 | |
| 85 | if(has_BPB4) { |
| 86 | printf("physical drive id: 0x%x\n", |
| 87 | labelBlock->physdrive); |
| 88 | printf("reserved=0x%x\n", |
| 89 | labelBlock->reserved); |
| 90 | printf("dos4=0x%x\n", |
| 91 | labelBlock->dos4); |
| 92 | printf("serial number: %08X\n", |
| 93 | _DWORD(labelBlock->serial)); |
| 94 | printf("disk label=\"%11.11s\"\n", |
| 95 | labelBlock->label); |
| 96 | printf("disk type=\"%8.8s\"\n", |
| 97 | labelBlock->fat_type); |
| 98 | } |
| 99 | |
| 100 | if(!WORD(fatlen)){ |
| 101 | printf("Big fatlen=%u\n", |
| 102 | DWORD(ext.fat32.bigFat)); |
| 103 | printf("Extended flags=0x%04x\n", |
| 104 | WORD(ext.fat32.extFlags)); |
| 105 | printf("FS version=0x%04x\n", |
| 106 | WORD(ext.fat32.fsVersion)); |
| 107 | printf("rootCluster=%u\n", |
| 108 | DWORD(ext.fat32.rootCluster)); |
| 109 | if(WORD(ext.fat32.infoSector) != MAX16) |
| 110 | printf("infoSector location=%d\n", |
| 111 | WORD(ext.fat32.infoSector)); |
| 112 | if(WORD(ext.fat32.backupBoot) != MAX16) |
| 113 | printf("backup boot sector=%d\n", |
| 114 | WORD(ext.fat32.backupBoot)); |
| 115 | displayInfosector(Stream, boot); |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | void minfo(int argc, char **argv, int type UNUSEDP) NORETURN; |
| 120 | void minfo(int argc, char **argv, int type UNUSEDP) |
| 121 | { |
| 122 | union bootsector boot; |
| 123 | |
| 124 | char name[EXPAND_BUF]; |
| 125 | int media; |
| 126 | int haveBPB; |
| 127 | int size_code; |
| 128 | int i; |
| 129 | struct device dev; |
| 130 | char drive; |
| 131 | int verbose=0; |
| 132 | int c; |
| 133 | Stream_t *Stream; |
| 134 | int have_drive = 0; |
| 135 | |
| 136 | unsigned long sect_per_track; |
| 137 | |
| 138 | char *imgFile=NULL; |
| 139 | |
| 140 | if(helpFlag(argc, argv)) |
| 141 | usage(0); |
| 142 | while ((c = getopt(argc, argv, "i:vh")) != EOF) { |
| 143 | switch (c) { |
| 144 | case 'i': |
| 145 | set_cmd_line_image(optarg); |
| 146 | imgFile=optarg; |
| 147 | break; |
| 148 | case 'v': |
| 149 | verbose = 1; |
| 150 | break; |
| 151 | case 'h': |
| 152 | usage(0); |
| 153 | default: |
| 154 | usage(1); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | for(;optind <= argc; optind++) { |
| 159 | if(optind == argc) { |
| 160 | if(have_drive) |
| 161 | break; |
| 162 | drive = get_default_drive(); |
| 163 | } else { |
| 164 | if(!argv[optind][0] || argv[optind][1] != ':') |
| 165 | usage(1); |
| 166 | drive = ch_toupper(argv[optind][0]); |
| 167 | } |
| 168 | have_drive = 1; |
| 169 | |
| 170 | if(! (Stream = find_device(drive, O_RDONLY, &dev, &boot, |
| 171 | name, &media, 0, NULL))) |
| 172 | exit(1); |
| 173 | |
| 174 | haveBPB = media >= 0x100; |
| 175 | media = media & 0xff; |
| 176 | |
| 177 | printf("device information:\n"); |
| 178 | printf("===================\n"); |
| 179 | printf("filename=\"%s\"\n", name); |
| 180 | printf("sectors per track: %d\n", dev.sectors); |
| 181 | printf("heads: %d\n", dev.heads); |
| 182 | printf("cylinders: %d\n\n", dev.tracks); |
| 183 | printf("media byte: %02x\n\n", media & 0xff); |
| 184 | |
| 185 | sect_per_track = dev.sectors * dev.heads; |
| 186 | if(sect_per_track != 0) { |
| 187 | unsigned int hidden; |
| 188 | unsigned long tot_sectors; |
| 189 | int tracks_match=0; |
| 190 | printf("mformat command line: mformat "); |
| 191 | |
| 192 | if(haveBPB) { |
| 193 | int sector_size; |
| 194 | tot_sectors = DWORD_S(bigsect); |
| 195 | SET_INT(tot_sectors, WORD_S(psect)); |
| 196 | sector_size = WORD_S(secsiz); |
| 197 | size_code=2; |
| 198 | for(i=0; i<7; i++) { |
| 199 | if(sector_size == 128 << i) { |
| 200 | size_code = i; |
| 201 | break; |
| 202 | } |
| 203 | } |
| 204 | if(media == 0xf0) |
| 205 | hidden = DWORD_S(nhs); |
| 206 | else |
| 207 | hidden = 0; |
| 208 | } else { |
| 209 | tot_sectors = dev.tracks * sect_per_track; |
| 210 | size_code=2; |
| 211 | hidden = 0; |
| 212 | } |
| 213 | |
| 214 | if(tot_sectors == |
| 215 | dev.tracks * sect_per_track - hidden % sect_per_track) { |
| 216 | tracks_match=1; |
| 217 | printf("-t %d ", dev.tracks); |
| 218 | } else { |
| 219 | printf("-T %ld ", tot_sectors); |
| 220 | } |
| 221 | printf ("-h %d -s %d ", dev.heads, dev.sectors); |
| 222 | if(haveBPB && (hidden || !tracks_match)) |
| 223 | printf("-H %d ", hidden); |
| 224 | if(size_code != 2) |
| 225 | printf("-S %d ",size_code); |
| 226 | if(imgFile != NULL) |
| 227 | printf("-i \"%s\" ", imgFile); |
| 228 | printf("%c:\n", ch_tolower(drive)); |
| 229 | printf("\n"); |
| 230 | } |
| 231 | |
| 232 | if(haveBPB || verbose) |
| 233 | displayBPB(Stream, &boot); |
| 234 | |
| 235 | if(verbose) { |
| 236 | int size; |
| 237 | unsigned char *buf; |
| 238 | |
| 239 | printf("\n"); |
| 240 | size = WORD_S(secsiz); |
| 241 | |
| 242 | buf = (unsigned char *) malloc(size); |
| 243 | if(!buf) { |
| 244 | fprintf(stderr, "Out of memory error\n"); |
| 245 | exit(1); |
| 246 | } |
| 247 | |
| 248 | size = READS(Stream, buf, (mt_off_t) 0, size); |
| 249 | if(size < 0) { |
| 250 | perror("read boot sector"); |
| 251 | exit(1); |
| 252 | } |
| 253 | |
| 254 | print_sector("Boot sector hexdump", buf, size); |
| 255 | } |
| 256 | } |
| 257 | FREE(&Stream); |
| 258 | exit(0); |
| 259 | } |