blob: 07a1773032f163157c2d5c47798b368fec0c4f9d [file] [log] [blame]
Alistair Delvabeaee832021-02-24 11:27:23 -08001/* 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"
Yi Kong39bbd962022-01-09 19:41:38 +080027#include "fsP.h"
Alistair Delvabeaee832021-02-24 11:27:23 -080028
29static void usage(int ret) NORETURN;
30static void usage(int ret)
31{
Yi Kong39bbd962022-01-09 19:41:38 +080032 fprintf(stderr,
Alistair Delvabeaee832021-02-24 11:27:23 -080033 "Mtools version %s, dated %s\n", mversion, mdate);
Yi Kong39bbd962022-01-09 19:41:38 +080034 fprintf(stderr,
Alistair Delvabeaee832021-02-24 11:27:23 -080035 "Usage: %s [-v] drive\n", progname);
36 exit(ret);
37}
38
39
40static void displayInfosector(Stream_t *Stream, union bootsector *boot)
41{
42 InfoSector_t *infosec;
43
44 if(WORD(ext.fat32.infoSector) == MAX16)
45 return;
46
47 infosec = (InfoSector_t *) safe_malloc(WORD(secsiz));
Yi Kong39bbd962022-01-09 19:41:38 +080048 force_pread(Stream, (char *) infosec,
49 (mt_off_t) WORD(secsiz) * WORD(ext.fat32.infoSector),
50 WORD(secsiz));
Alistair Delvabeaee832021-02-24 11:27:23 -080051 printf("\nInfosector:\n");
52 printf("signature=0x%08x\n", _DWORD(infosec->signature1));
53 if(_DWORD(infosec->count) != MAX32)
54 printf("free clusters=%u\n", _DWORD(infosec->count));
55 if(_DWORD(infosec->pos) != MAX32)
56 printf("last allocated cluster=%u\n", _DWORD(infosec->pos));
57}
58
Yi Kong39bbd962022-01-09 19:41:38 +080059/*
60 * Number of hidden sector is only a 4 byte quantity if number of sectors is
61 */
62static uint32_t getHidden(union bootsector *boot) {
63 return WORD(psect) ? WORD(nhs) : DWORD(nhs);
64}
Alistair Delvabeaee832021-02-24 11:27:23 -080065
66static void displayBPB(Stream_t *Stream, union bootsector *boot) {
67 struct label_blk_t *labelBlock;
68
69 printf("bootsector information\n");
70 printf("======================\n");
71 printf("banner:\"%.8s\"\n", boot->boot.banner);
72 printf("sector size: %d bytes\n", WORD(secsiz));
73 printf("cluster size: %d sectors\n", boot->boot.clsiz);
74 printf("reserved (boot) sectors: %d\n", WORD(nrsvsect));
75 printf("fats: %d\n", boot->boot.nfat);
Yi Kong39bbd962022-01-09 19:41:38 +080076 printf("max available root directory slots: %d\n",
Alistair Delvabeaee832021-02-24 11:27:23 -080077 WORD(dirents));
78 printf("small size: %d sectors\n", WORD(psect));
79 printf("media descriptor byte: 0x%x\n", boot->boot.descr);
80 printf("sectors per fat: %d\n", WORD(fatlen));
81 printf("sectors per track: %d\n", WORD(nsect));
82 printf("heads: %d\n", WORD(nheads));
Yi Kong39bbd962022-01-09 19:41:38 +080083 printf("hidden sectors: %d\n", getHidden(boot));
84 if(!WORD(psect))
85 printf("big size: %u sectors\n", DWORD(bigsect));
Alistair Delvabeaee832021-02-24 11:27:23 -080086
87 if(WORD(fatlen)) {
88 labelBlock = &boot->boot.ext.old.labelBlock;
89 } else {
90 labelBlock = &boot->boot.ext.fat32.labelBlock;
91 }
92
93 if(has_BPB4) {
Yi Kong39bbd962022-01-09 19:41:38 +080094 printf("physical drive id: 0x%x\n",
Alistair Delvabeaee832021-02-24 11:27:23 -080095 labelBlock->physdrive);
Yi Kong39bbd962022-01-09 19:41:38 +080096 printf("reserved=0x%x\n",
Alistair Delvabeaee832021-02-24 11:27:23 -080097 labelBlock->reserved);
Yi Kong39bbd962022-01-09 19:41:38 +080098 printf("dos4=0x%x\n",
Alistair Delvabeaee832021-02-24 11:27:23 -080099 labelBlock->dos4);
Yi Kong39bbd962022-01-09 19:41:38 +0800100 printf("serial number: %08X\n",
Alistair Delvabeaee832021-02-24 11:27:23 -0800101 _DWORD(labelBlock->serial));
Yi Kong39bbd962022-01-09 19:41:38 +0800102 printf("disk label=\"%11.11s\"\n",
Alistair Delvabeaee832021-02-24 11:27:23 -0800103 labelBlock->label);
Yi Kong39bbd962022-01-09 19:41:38 +0800104 printf("disk type=\"%8.8s\"\n",
Alistair Delvabeaee832021-02-24 11:27:23 -0800105 labelBlock->fat_type);
106 }
Yi Kong39bbd962022-01-09 19:41:38 +0800107
Alistair Delvabeaee832021-02-24 11:27:23 -0800108 if(!WORD(fatlen)){
109 printf("Big fatlen=%u\n",
110 DWORD(ext.fat32.bigFat));
111 printf("Extended flags=0x%04x\n",
112 WORD(ext.fat32.extFlags));
113 printf("FS version=0x%04x\n",
114 WORD(ext.fat32.fsVersion));
115 printf("rootCluster=%u\n",
116 DWORD(ext.fat32.rootCluster));
117 if(WORD(ext.fat32.infoSector) != MAX16)
118 printf("infoSector location=%d\n",
119 WORD(ext.fat32.infoSector));
120 if(WORD(ext.fat32.backupBoot) != MAX16)
121 printf("backup boot sector=%d\n",
122 WORD(ext.fat32.backupBoot));
123 displayInfosector(Stream, boot);
124 }
125}
126
Yi Kong39bbd962022-01-09 19:41:38 +0800127static int try(uint32_t tot_sectors, Fs_t *masterFs, Fs_t *tryFs,
128 struct device *master_dev, struct device *try_dev,
129 uint8_t *bootDescr) {
130 *tryFs = *masterFs;
131 *try_dev = *master_dev;
132 return calc_fs_parameters(try_dev, 0, tot_sectors,
133 tryFs, bootDescr);
134}
135
136static void print_mformat_commandline(const char *imgFile,
137 char drive,
138 struct device *dev,
139 union bootsector *boot,
140 int media,
141 int haveBPB) {
142 uint8_t size_code;
143 uint32_t sect_per_track;
144 uint32_t hidden;
145 uint32_t tot_sectors;
146 int tracks_match=0;
147 Fs_t masterFs, tryFs, actual;
148 struct device used_dev;
149 uint8_t tryMedia;
150 int bad;
151
152 sect_per_track = dev->sectors * dev->heads;
153 if(sect_per_track == 0)
154 return;
155
156 tot_sectors = parseFsParams(&actual, boot,
157 media | (haveBPB ? 0x100:0),
158 sect_per_track);
159 if(tot_sectors == 0)
160 return;
161
162 printf("mformat command line:\n mformat ");
163
164 if(haveBPB) {
165 if(media == 0xf0)
166 hidden = getHidden(boot);
167 else
168 hidden = 0;
169 size_code = (uint8_t) actual.sectorShift-7;
170 } else {
171 size_code=2;
172 hidden = 0;
173 }
174
175 if(tot_sectors ==
176 dev->tracks * sect_per_track - hidden % sect_per_track) {
177 tracks_match=1;
178 printf("-t %d ", dev->tracks);
179 } else {
180 printf("-T %d ", tot_sectors);
181 }
182 printf ("-h %d -s %d ", dev->heads, dev->sectors);
183 if(haveBPB && (hidden || !tracks_match))
184 printf("-H %d ", hidden);
185 used_dev=*dev;
186 if(size_code != 2) {
187 printf("-S %d ",size_code);
188 used_dev.ssize = size_code;
189 }
190
191 initFsForFormat(&masterFs);
192 setFsSectorSize(&masterFs, &used_dev, 0);
193
194 if(actual.num_fat != 2) {
195 masterFs.num_fat = actual.num_fat;
196 printf("-d %d ", actual.num_fat);
197 }
198
199 bad=try(tot_sectors, &masterFs, &tryFs, dev , &used_dev, &tryMedia);
200
201 if(bad || actual.dir_len != tryFs.dir_len) {
202 masterFs.dir_len = actual.dir_len;
203 printf("-r %d ", actual.dir_len);
204 bad = try(tot_sectors,
205 &masterFs, &tryFs, dev , &used_dev,
206 &tryMedia);
207 }
208
209 if(bad || actual.cluster_size != tryFs.cluster_size) {
210 masterFs.cluster_size = actual.cluster_size;
211 printf("-c %d ", actual.cluster_size);
212 bad = try(tot_sectors,
213 &masterFs, &tryFs, dev , &used_dev,
214 &tryMedia);
215 }
216
217 if(bad || actual.fat_start != tryFs.fat_start) {
218 masterFs.fat_start = actual.fat_start;
219 printf("-R %d ", actual.fat_start);
220 bad = try(tot_sectors,
221 &masterFs, &tryFs, dev , &used_dev,
222 &tryMedia);
223 }
224
225 if(bad || actual.fat_len != tryFs.fat_len) {
226 masterFs.fat_len = actual.fat_len;
227 printf("-L %d ", actual.fat_len);
228 bad = try(tot_sectors,
229 &masterFs, &tryFs, dev , &used_dev,
230 &tryMedia);
231 }
232#ifdef HAVE_ASSERT_H
233 assert(!bad);
234#endif
235 if((media & 0xff) != (tryMedia & 0xff))
236 printf("-m %d ", (media & 0xff));
237
238 if(actual.fat_bits == 32) {
239 if(actual.backupBoot != tryFs.backupBoot)
240 printf("-K %d ", actual.backupBoot);
241 }
242
243 if(imgFile != NULL)
244 printf("-i \"%s\" ", imgFile);
245 printf("%c:\n", ch_tolower(drive));
246 printf("\n");
247}
248
249
Alistair Delvabeaee832021-02-24 11:27:23 -0800250void minfo(int argc, char **argv, int type UNUSEDP) NORETURN;
251void minfo(int argc, char **argv, int type UNUSEDP)
252{
253 union bootsector boot;
254
255 char name[EXPAND_BUF];
Alistair Delvabeaee832021-02-24 11:27:23 -0800256 struct device dev;
257 char drive;
258 int verbose=0;
259 int c;
260 Stream_t *Stream;
261 int have_drive = 0;
Yi Kong39bbd962022-01-09 19:41:38 +0800262 int ex=0;
Alistair Delvabeaee832021-02-24 11:27:23 -0800263 char *imgFile=NULL;
Yi Kong39bbd962022-01-09 19:41:38 +0800264
Alistair Delvabeaee832021-02-24 11:27:23 -0800265 if(helpFlag(argc, argv))
266 usage(0);
267 while ((c = getopt(argc, argv, "i:vh")) != EOF) {
268 switch (c) {
269 case 'i':
270 set_cmd_line_image(optarg);
271 imgFile=optarg;
272 break;
273 case 'v':
274 verbose = 1;
275 break;
276 case 'h':
277 usage(0);
278 default:
279 usage(1);
280 }
281 }
282
283 for(;optind <= argc; optind++) {
Yi Kong39bbd962022-01-09 19:41:38 +0800284 int media;
285 int haveBPB;
286
Alistair Delvabeaee832021-02-24 11:27:23 -0800287 if(optind == argc) {
288 if(have_drive)
289 break;
290 drive = get_default_drive();
291 } else {
292 if(!argv[optind][0] || argv[optind][1] != ':')
293 usage(1);
294 drive = ch_toupper(argv[optind][0]);
295 }
296 have_drive = 1;
297
Yi Kong39bbd962022-01-09 19:41:38 +0800298 if(! (Stream = find_device(drive, O_RDONLY, &dev, &boot,
299 name, &media, 0, NULL))) {
300 fprintf(stderr, "Could not open drive %c:\n", drive);
301 ex=1;
302 continue;
303 }
Alistair Delvabeaee832021-02-24 11:27:23 -0800304
305 haveBPB = media >= 0x100;
306 media = media & 0xff;
Yi Kong39bbd962022-01-09 19:41:38 +0800307
Alistair Delvabeaee832021-02-24 11:27:23 -0800308 printf("device information:\n");
309 printf("===================\n");
310 printf("filename=\"%s\"\n", name);
311 printf("sectors per track: %d\n", dev.sectors);
312 printf("heads: %d\n", dev.heads);
313 printf("cylinders: %d\n\n", dev.tracks);
314 printf("media byte: %02x\n\n", media & 0xff);
315
Yi Kong39bbd962022-01-09 19:41:38 +0800316 print_mformat_commandline(imgFile, drive,
317 &dev, &boot, media, haveBPB);
Alistair Delvabeaee832021-02-24 11:27:23 -0800318
319 if(haveBPB || verbose)
320 displayBPB(Stream, &boot);
321
322 if(verbose) {
Yi Kong39bbd962022-01-09 19:41:38 +0800323 uint16_t size;
324 ssize_t ssize;
Alistair Delvabeaee832021-02-24 11:27:23 -0800325 unsigned char *buf;
326
327 printf("\n");
328 size = WORD_S(secsiz);
Yi Kong39bbd962022-01-09 19:41:38 +0800329
Alistair Delvabeaee832021-02-24 11:27:23 -0800330 buf = (unsigned char *) malloc(size);
331 if(!buf) {
332 fprintf(stderr, "Out of memory error\n");
333 exit(1);
334 }
335
Yi Kong39bbd962022-01-09 19:41:38 +0800336 ssize = PREADS(Stream, buf, 0, size);
337 if(ssize < 0) {
Alistair Delvabeaee832021-02-24 11:27:23 -0800338 perror("read boot sector");
339 exit(1);
340 }
341
Yi Kong39bbd962022-01-09 19:41:38 +0800342 print_sector("Boot sector hexdump", buf, (uint16_t)ssize);
Alistair Delvabeaee832021-02-24 11:27:23 -0800343 }
344 }
345 FREE(&Stream);
Yi Kong39bbd962022-01-09 19:41:38 +0800346 exit(ex);
Alistair Delvabeaee832021-02-24 11:27:23 -0800347}