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