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
28static void usage(int ret) NORETURN;
29static 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
39static void displayInfosector(Stream_t *Stream, struct 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
59void minfo(int argc, char **argv, int type)
60{
61	unsigned char boot0[MAX_BOOT];
62	struct bootsector *boot = (struct bootsector *) boot0;
63
64	char name[EXPAND_BUF];
65	int media;
66	int tot_sectors;
67	int size_code;
68	int sector_size;
69	int i;
70	struct device dev;
71	char drive;
72	int verbose=0;
73	int c;
74	Stream_t *Stream;
75	struct label_blk_t *labelBlock;
76
77	if(helpFlag(argc, argv))
78		usage(0);
79	while ((c = getopt(argc, argv, "i:vh")) != EOF) {
80		switch (c) {
81			case 'i':
82				set_cmd_line_image(optarg, 0);
83				break;
84			case 'v':
85				verbose = 1;
86				break;
87			case 'h':
88				usage(0);
89			default:
90				usage(1);
91		}
92	}
93
94	if(argc == optind)
95		usage(1);
96
97	for(;optind < argc; optind++) {
98		if(!argv[optind][0] || argv[optind][1] != ':')
99			usage(1);
100		drive = toupper(argv[optind][0]);
101
102		if(! (Stream = find_device(drive, O_RDONLY, &dev, boot,
103					   name, &media, 0, NULL)))
104			exit(1);
105
106		tot_sectors = DWORD(bigsect);
107		SET_INT(tot_sectors, WORD(psect));
108		sector_size = WORD(secsiz);
109		size_code=2;
110		for(i=0; i<7; i++) {
111			if(sector_size == 128 << i) {
112				size_code = i;
113				break;
114			}
115		}
116		printf("device information:\n");
117		printf("===================\n");
118		printf("filename=\"%s\"\n", name);
119		printf("sectors per track: %d\n", dev.sectors);
120		printf("heads: %d\n", dev.heads);
121		printf("cylinders: %d\n\n", dev.tracks);
122		printf("mformat command line: mformat -t %d -h %d -s %d ",
123		       dev.tracks, dev.heads, dev.sectors);
124		if(DWORD(nhs))
125			printf("-H %d ", DWORD(nhs));
126		if(size_code != 2)
127			printf("-S %d ",size_code);
128		printf("%c:\n", tolower(drive));
129		printf("\n");
130
131		printf("bootsector information\n");
132		printf("======================\n");
133		printf("banner:\"%8s\"\n", boot->banner);
134		printf("sector size: %d bytes\n", WORD(secsiz));
135		printf("cluster size: %d sectors\n", boot->clsiz);
136		printf("reserved (boot) sectors: %d\n", WORD(nrsvsect));
137		printf("fats: %d\n", boot->nfat);
138		printf("max available root directory slots: %d\n",
139		       WORD(dirents));
140		printf("small size: %d sectors\n", WORD(psect));
141		printf("media descriptor byte: 0x%x\n", boot->descr);
142		printf("sectors per fat: %d\n", WORD(fatlen));
143		printf("sectors per track: %d\n", WORD(nsect));
144		printf("heads: %d\n", WORD(nheads));
145		printf("hidden sectors: %d\n", DWORD(nhs));
146		printf("big size: %d sectors\n", DWORD(bigsect));
147
148		if(WORD(fatlen)) {
149		    labelBlock = &boot->ext.old.labelBlock;
150		} else {
151		    labelBlock = &boot->ext.fat32.labelBlock;
152		}
153
154		printf("physical drive id: 0x%x\n",
155		       labelBlock->physdrive);
156		printf("reserved=0x%x\n",
157		       labelBlock->reserved);
158		printf("dos4=0x%x\n",
159		       labelBlock->dos4);
160		printf("serial number: %08X\n",
161		       _DWORD(labelBlock->serial));
162		printf("disk label=\"%11.11s\"\n",
163		       labelBlock->label);
164		printf("disk type=\"%8.8s\"\n",
165		       labelBlock->fat_type);
166
167		if(!WORD(fatlen)){
168			printf("Big fatlen=%u\n",
169			       DWORD(ext.fat32.bigFat));
170			printf("Extended flags=0x%04x\n",
171			       WORD(ext.fat32.extFlags));
172			printf("FS version=0x%04x\n",
173			       WORD(ext.fat32.fsVersion));
174			printf("rootCluster=%u\n",
175			       DWORD(ext.fat32.rootCluster));
176			if(WORD(ext.fat32.infoSector) != MAX16)
177				printf("infoSector location=%d\n",
178				       WORD(ext.fat32.infoSector));
179			if(WORD(ext.fat32.backupBoot) != MAX16)
180				printf("backup boot sector=%d\n",
181				       WORD(ext.fat32.backupBoot));
182			displayInfosector(Stream,boot);
183		}
184
185		if(verbose) {
186			int size;
187			unsigned char *buf;
188
189			printf("\n");
190			size = WORD(secsiz);
191
192			buf = (unsigned char *) malloc(size);
193			if(!buf) {
194				fprintf(stderr, "Out of memory error\n");
195				exit(1);
196			}
197
198			size = READS(Stream, buf, (mt_off_t) 0, size);
199			if(size < 0) {
200				perror("read boot sector");
201				exit(1);
202			}
203
204			print_sector("Boot sector hexdump", buf, size);
205		}
206	}
207	FREE(&Stream);
208	exit(0);
209}
210