dosfstools  4.2
About: dosfstools are utilities to create, check and label (MS-DOS) FAT filesystems.
  Fossies Dox: dosfstools-4.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

boot.c
Go to the documentation of this file.
1 /* boot.c - Read and analyze ia PC/MS-DOS boot sector
2 
3  Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
4  Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
5  Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
6  Copyright (C) 2015-2017 Andreas Bombe <aeb@debian.org>
7  Copyright (C) 2018-2021 Pali Roh├ír <pali.rohar@gmail.com>
8 
9  This program is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program. If not, see <http://www.gnu.org/licenses/>.
21 
22  The complete text of the GNU General Public License
23  can be found in /usr/share/common-licenses/GPL-3 file.
24 */
25 
26 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
27  * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
28 
29 #include <limits.h>
30 #include <stdio.h>
31 #include <stdint.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <time.h>
36 
37 #include "common.h"
38 #include "fsck.fat.h"
39 #include "fat.h"
40 #include "io.h"
41 #include "boot.h"
42 #include "check.h"
43 #include "charconv.h"
44 
45 #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
46  /* don't divide by zero */
47 
48 /* cut-over cluster counts for FAT12 and FAT16 */
49 #define FAT12_THRESHOLD 4085
50 #define FAT16_THRESHOLD 65525
51 
52 off_t alloc_rootdir_entry(DOS_FS * fs, DIR_ENT * de, const char *pattern, int gen_name)
53 {
54  static int curr_num = 0;
55  off_t offset;
56 
57  if (fs->root_cluster) {
58  DIR_ENT d2;
59  int i = 0, got = 0;
60  uint32_t clu_num, prev = 0;
61  off_t offset2;
62 
63  clu_num = fs->root_cluster;
64  offset = cluster_start(fs, clu_num);
65  while (clu_num > 0 && clu_num != -1) {
66  fs_read(offset, sizeof(DIR_ENT), &d2);
67  if (IS_FREE(d2.name) && d2.attr != VFAT_LN_ATTR) {
68  got = 1;
69  break;
70  }
71  i += sizeof(DIR_ENT);
72  offset += sizeof(DIR_ENT);
73  if ((i % fs->cluster_size) == 0) {
74  prev = clu_num;
75  if ((clu_num = next_cluster(fs, clu_num)) == 0 || clu_num == -1)
76  break;
77  offset = cluster_start(fs, clu_num);
78  }
79  }
80  if (!got) {
81  /* no free slot, need to extend root dir: alloc next free cluster
82  * after previous one */
83  if (!prev)
84  die("Root directory has no cluster allocated!");
85  for (clu_num = prev + 1; clu_num != prev; clu_num++) {
86  FAT_ENTRY entry;
87 
88  if (clu_num >= fs->data_clusters + 2)
89  clu_num = 2;
90  get_fat(&entry, fs->fat, clu_num, fs);
91  if (!entry.value)
92  break;
93  }
94  if (clu_num == prev)
95  die("Root directory full and no free cluster");
96  set_fat(fs, prev, clu_num);
97  set_fat(fs, clu_num, -1);
98  set_owner(fs, clu_num, get_owner(fs, fs->root_cluster));
99  /* clear new cluster */
100  memset(&d2, 0, sizeof(d2));
101  offset = cluster_start(fs, clu_num);
102  for (i = 0; i < fs->cluster_size; i += sizeof(DIR_ENT))
103  fs_write(offset + i, sizeof(d2), &d2);
104  }
105  memset(de, 0, sizeof(DIR_ENT));
106  if (gen_name) {
107  while (1) {
108  char expanded[12];
109  sprintf(expanded, pattern, curr_num);
110  memcpy(de->name, expanded, MSDOS_NAME);
111  clu_num = fs->root_cluster;
112  i = 0;
113  offset2 = cluster_start(fs, clu_num);
114  while (clu_num > 0 && clu_num != -1) {
115  fs_read(offset2, sizeof(DIR_ENT), &d2);
116  if (offset2 != offset &&
117  !strncmp((const char *)d2.name, (const char *)de->name,
118  MSDOS_NAME))
119  break;
120  i += sizeof(DIR_ENT);
121  offset2 += sizeof(DIR_ENT);
122  if ((i % fs->cluster_size) == 0) {
123  if ((clu_num = next_cluster(fs, clu_num)) == 0 ||
124  clu_num == -1)
125  break;
126  offset2 = cluster_start(fs, clu_num);
127  }
128  }
129  if (clu_num == 0 || clu_num == -1)
130  break;
131  if (++curr_num >= 10000)
132  die("Unable to create unique name");
133  }
134  } else {
135  memcpy(de->name, pattern, MSDOS_NAME);
136  }
137  } else {
138  DIR_ENT *root;
139  int next_free = 0, scan;
140 
141  root = alloc(fs->root_entries * sizeof(DIR_ENT));
142  fs_read(fs->root_start, fs->root_entries * sizeof(DIR_ENT), root);
143 
144  while (next_free < fs->root_entries)
145  if (IS_FREE(root[next_free].name) &&
146  root[next_free].attr != VFAT_LN_ATTR)
147  break;
148  else
149  next_free++;
150  if (next_free == fs->root_entries)
151  die("Root directory is full.");
152  offset = fs->root_start + next_free * sizeof(DIR_ENT);
153  memset(de, 0, sizeof(DIR_ENT));
154  if (gen_name) {
155  while (1) {
156  char expanded[12];
157  sprintf(expanded, pattern, curr_num);
158  memcpy(de->name, expanded, MSDOS_NAME);
159  for (scan = 0; scan < fs->root_entries; scan++)
160  if (scan != next_free &&
161  !strncmp((const char *)root[scan].name,
162  (const char *)de->name, MSDOS_NAME))
163  break;
164  if (scan == fs->root_entries)
165  break;
166  if (++curr_num >= 10000)
167  die("Unable to create unique name");
168  }
169  } else {
170  memcpy(de->name, pattern, MSDOS_NAME);
171  }
172  free(root);
173  }
174  ++n_files;
175  return offset;
176 }
177 
178 static struct {
179  uint8_t media;
180  const char *descr;
181 } mediabytes[] = {
182  {
183  0xf0, "5.25\" or 3.5\" HD floppy"}, {
184  0xf8, "hard disk"}, {
185  0xf9, "3,5\" 720k floppy 2s/80tr/9sec or "
186  "5.25\" 1.2M floppy 2s/80tr/15sec"}, {
187  0xfa, "5.25\" 320k floppy 1s/80tr/8sec"}, {
188  0xfb, "3.5\" 640k floppy 2s/80tr/8sec"}, {
189  0xfc, "5.25\" 180k floppy 1s/40tr/9sec"}, {
190  0xfd, "5.25\" 360k floppy 2s/40tr/9sec"}, {
191  0xfe, "5.25\" 160k floppy 1s/40tr/8sec"}, {
192 0xff, "5.25\" 320k floppy 2s/40tr/8sec"},};
193 
194 /* Unaligned fields must first be accessed byte-wise */
195 #define GET_UNALIGNED_W(f) \
196  ( (uint16_t)f[0] | ((uint16_t)f[1]<<8) )
197 
198 static const char *get_media_descr(unsigned char media)
199 {
200  int i;
201 
202  for (i = 0; i < sizeof(mediabytes) / sizeof(*mediabytes); ++i) {
203  if (mediabytes[i].media == media)
204  return (mediabytes[i].descr);
205  }
206  return ("undefined");
207 }
208 
209 static void dump_boot(DOS_FS * fs, struct boot_sector *b, unsigned lss)
210 {
211  unsigned short sectors;
212 
213  printf("Boot sector contents:\n");
214  if (!atari_format) {
215  char id[9];
216  strncpy(id, (const char *)b->system_id, 8);
217  id[8] = 0;
218  printf("System ID \"%s\"\n", id);
219  } else {
220  /* On Atari, a 24 bit serial number is stored at offset 8 of the boot
221  * sector */
222  printf("Serial number 0x%x\n",
223  b->system_id[5] | (b->system_id[6] << 8) | (b->
224  system_id[7] << 16));
225  }
226  printf("Media byte 0x%02x (%s)\n", b->media, get_media_descr(b->media));
227  printf("%10d bytes per logical sector\n", GET_UNALIGNED_W(b->sector_size));
228  printf("%10d bytes per cluster\n", fs->cluster_size);
229  printf("%10d reserved sector%s\n", le16toh(b->reserved),
230  le16toh(b->reserved) == 1 ? "" : "s");
231  printf("First FAT starts at byte %llu (sector %llu)\n",
232  (unsigned long long)fs->fat_start,
233  (unsigned long long)fs->fat_start / lss);
234  printf("%10d FATs, %d bit entries\n", b->fats, fs->fat_bits);
235  printf("%10u bytes per FAT (= %u sectors)\n", fs->fat_size,
236  fs->fat_size / lss);
237  if (!fs->root_cluster) {
238  printf("Root directory starts at byte %llu (sector %llu)\n",
239  (unsigned long long)fs->root_start,
240  (unsigned long long)fs->root_start / lss);
241  printf("%10d root directory entries\n", fs->root_entries);
242  } else {
243  printf("Root directory start at cluster %lu (arbitrary size)\n",
244  (unsigned long)fs->root_cluster);
245  }
246  printf("Data area starts at byte %llu (sector %llu)\n",
247  (unsigned long long)fs->data_start,
248  (unsigned long long)fs->data_start / lss);
249  printf("%10lu data clusters (%llu bytes)\n",
250  (unsigned long)fs->data_clusters,
251  (unsigned long long)fs->data_clusters * fs->cluster_size);
252  printf("%u sectors/track, %u heads\n", le16toh(b->secs_track),
253  le16toh(b->heads));
254  printf("%10u hidden sectors\n", atari_format ?
255  /* On Atari, the hidden field is only 16 bit wide and unused */
256  (((unsigned char *)&b->hidden)[0] |
257  ((unsigned char *)&b->hidden)[1] << 8) : le32toh(b->hidden));
258  sectors = GET_UNALIGNED_W(b->sectors);
259  printf("%10u sectors total\n", sectors ? sectors : le32toh(b->total_sect));
260 }
261 
262 static void check_backup_boot(DOS_FS * fs, struct boot_sector *b, unsigned int lss)
263 {
264  struct boot_sector b2;
265 
266  if (!fs->backupboot_start) {
267  printf("There is no backup boot sector.\n");
268  if (le16toh(b->reserved) < 3) {
269  printf("And there is no space for creating one!\n");
270  return;
271  }
272  if (get_choice(1, " Auto-creating backup boot block.",
273  2,
274  1, "Create one",
275  2, "Do without a backup") == 1) {
276  unsigned int bbs;
277  /* The usual place for the backup boot sector is sector 6. Choose
278  * that or the last reserved sector. */
279  if (le16toh(b->reserved) >= 7 && le16toh(b->info_sector) != 6)
280  bbs = 6;
281  else {
282  bbs = le16toh(b->reserved) - 1;
283  if (bbs == le16toh(b->info_sector))
284  --bbs; /* this is never 0, as we checked reserved >= 3! */
285  }
286  fs->backupboot_start = bbs * lss;
287  b->backup_boot = htole16(bbs);
288  fs_write(fs->backupboot_start, sizeof(*b), b);
289  fs_write(offsetof(struct boot_sector, backup_boot),
290  sizeof(b->backup_boot), &b->backup_boot);
291  printf("Created backup of boot sector in sector %d\n", bbs);
292  return;
293  } else
294  return;
295  }
296 
297  fs_read(fs->backupboot_start, sizeof(b2), &b2);
298  if (memcmp(b, &b2, sizeof(b2)) != 0) {
299  /* there are any differences */
300  uint8_t *p, *q;
301  int i, pos, first = 1;
302  char buf[32];
303 
304  printf("There are differences between boot sector and its backup.\n");
305  printf("This is mostly harmless. Differences: (offset:original/backup)\n ");
306  pos = 2;
307  for (p = (uint8_t *) b, q = (uint8_t *) & b2, i = 0; i < sizeof(b2);
308  ++p, ++q, ++i) {
309  if (*p != *q) {
310  sprintf(buf, "%s%u:%02x/%02x", first ? "" : ", ",
311  (unsigned)(p - (uint8_t *) b), *p, *q);
312  if (pos + strlen(buf) > 78)
313  printf("\n "), pos = 2;
314  printf("%s", buf);
315  pos += strlen(buf);
316  first = 0;
317  }
318  }
319  printf("\n");
320 
321  switch (get_choice(3, " Not automatically fixing this.",
322  3,
323  1, "Copy original to backup",
324  2, "Copy backup to original",
325  3, "No action")) {
326  case 1:
327  fs_write(fs->backupboot_start, sizeof(*b), b);
328  break;
329  case 2:
330  fs_write(0, sizeof(b2), &b2);
331  break;
332  default:
333  break;
334  }
335  }
336 }
337 
339 {
340  i->magic = htole32(0x41615252);
341  i->signature = htole32(0x61417272);
342  i->free_clusters = htole32(-1);
343  i->next_cluster = htole32(2);
344  i->boot_sign = htole32(0xaa550000);
345 }
346 
347 static void read_fsinfo(DOS_FS * fs, struct boot_sector *b, unsigned int lss)
348 {
349  struct info_sector i;
350 
351  if (!b->info_sector) {
352  printf("No FSINFO sector\n");
353  if (get_choice(2, " Not automatically creating it.",
354  2,
355  1, "Create one",
356  2, "Do without FSINFO") == 1) {
357  /* search for a free reserved sector (not boot sector and not
358  * backup boot sector) */
359  uint32_t s;
360  for (s = 1; s < le16toh(b->reserved); ++s)
361  if (s != le16toh(b->backup_boot))
362  break;
363  if (s > 0 && s < le16toh(b->reserved)) {
364  memset(&i, 0, sizeof (struct info_sector));
366  fs_write((off_t)s * lss, sizeof(i), &i);
367  b->info_sector = htole16(s);
368  fs_write(offsetof(struct boot_sector, info_sector),
369  sizeof(b->info_sector), &b->info_sector);
370  if (fs->backupboot_start)
372  offsetof(struct boot_sector, info_sector),
373  sizeof(b->info_sector), &b->info_sector);
374  } else {
375  printf("No free reserved sector found -- "
376  "no space for FSINFO sector!\n");
377  return;
378  }
379  } else
380  return;
381  }
382 
383  fs->fsinfo_start = le16toh(b->info_sector) * lss;
384  fs_read(fs->fsinfo_start, sizeof(i), &i);
385 
386  if (i.magic != htole32(0x41615252) ||
387  i.signature != htole32(0x61417272) || i.boot_sign != htole32(0xaa550000)) {
388  printf("FSINFO sector has bad magic number(s):\n");
389  if (i.magic != htole32(0x41615252))
390  printf(" Offset %llu: 0x%08x != expected 0x%08x\n",
391  (unsigned long long)offsetof(struct info_sector, magic),
392  le32toh(i.magic), 0x41615252);
393  if (i.signature != htole32(0x61417272))
394  printf(" Offset %llu: 0x%08x != expected 0x%08x\n",
395  (unsigned long long)offsetof(struct info_sector, signature),
396  le32toh(i.signature), 0x61417272);
397  if (i.boot_sign != htole32(0xaa550000))
398  printf(" Offset %llu: 0x%08x != expected 0x%08x\n",
399  (unsigned long long)offsetof(struct info_sector, boot_sign),
400  le32toh(i.boot_sign), 0xaa550000);
401  if (get_choice(1, " Auto-correcting it.",
402  2,
403  1, "Correct",
404  2, "Don't correct (FSINFO invalid then)") == 1) {
406  fs_write(fs->fsinfo_start, sizeof(i), &i);
407  } else
408  fs->fsinfo_start = 0;
409  }
410 
411  if (fs->fsinfo_start)
412  fs->free_clusters = le32toh(i.free_clusters);
413 }
414 
415 void read_boot(DOS_FS * fs)
416 {
417  struct boot_sector b;
418  unsigned total_sectors;
419  unsigned int logical_sector_size, sectors;
420  long long fat_length;
421  unsigned total_fat_entries;
422  off_t data_size;
423  long long position;
424 
425  fs_read(0, sizeof(b), &b);
426  logical_sector_size = GET_UNALIGNED_W(b.sector_size);
427  if (!logical_sector_size)
428  die("Logical sector size is zero.");
429 
430  /* This was moved up because it's the first thing that will fail */
431  /* if the platform needs special handling of unaligned multibyte accesses */
432  /* but such handling isn't being provided. See GET_UNALIGNED_W() above. */
433  if (logical_sector_size & (SECTOR_SIZE - 1))
434  die("Logical sector size (%u bytes) is not a multiple of the physical "
435  "sector size.", logical_sector_size);
436 
437  fs->cluster_size = b.cluster_size * logical_sector_size;
438  if (!fs->cluster_size)
439  die("Cluster size is zero.");
440  if (b.fats != 2 && b.fats != 1)
441  die("Currently, only 1 or 2 FATs are supported, not %d.\n", b.fats);
442  fs->nfats = b.fats;
444  total_sectors = sectors ? sectors : le32toh(b.total_sect);
445  if (verbose)
446  printf("Checking we can access the last sector of the filesystem\n");
447  /* Can't access last odd sector anyway, so round down */
448  position = (long long)((total_sectors & ~1) - 1) * logical_sector_size;
449  if (position > OFF_MAX)
450  die("Filesystem is too large.");
451  if (!fs_test(position, logical_sector_size))
452  die("Failed to read sector %u.", (total_sectors & ~1) - 1);
453 
454  fat_length = le16toh(b.fat_length) ?
455  le16toh(b.fat_length) : le32toh(b.fat32_length);
456  if (!fat_length)
457  die("FAT size is zero.");
458 
459  fs->fat_start = (off_t)le16toh(b.reserved) * logical_sector_size;
460  position = (le16toh(b.reserved) + b.fats * fat_length) *
461  logical_sector_size;
462  if (position > OFF_MAX)
463  die("Filesystem is too large.");
464  fs->root_start = position;
466  position = (long long)fs->root_start +
468  logical_sector_size);
469  if (position > OFF_MAX)
470  die("Filesystem is too large.");
471  fs->data_start = position;
472  position = (long long)total_sectors * logical_sector_size - fs->data_start;
473  if (position > OFF_MAX)
474  die("Filesystem is too large.");
475  data_size = position;
476  if (data_size < fs->cluster_size)
477  die("Filesystem has no space for any data clusters");
478 
479  fs->data_clusters = data_size / fs->cluster_size;
480  fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */
481  fs->fsinfo_start = 0; /* no FSINFO structure */
482  fs->free_clusters = -1; /* unknown */
483  if (!b.fat_length && b.fat32_length) {
484  fs->fat_bits = 32;
485  fs->root_cluster = le32toh(b.root_cluster);
486  if (!fs->root_cluster && fs->root_entries)
487  /* M$ hasn't specified this, but it looks reasonable: If
488  * root_cluster is 0 but there is a separate root dir
489  * (root_entries != 0), we handle the root dir the old way. Give a
490  * warning, but convertig to a root dir in a cluster chain seems
491  * to complex for now... */
492  fprintf(stderr, "Warning: FAT32 root dir not in cluster chain! "
493  "Compatibility mode...\n");
494  else if (!fs->root_cluster && !fs->root_entries)
495  die("No root directory!");
496  else if (fs->root_cluster && fs->root_entries)
497  fprintf(stderr, "Warning: FAT32 root dir is in a cluster chain, but "
498  "a separate root dir\n"
499  " area is defined. Cannot fix this easily.\n");
500  if (fs->data_clusters < FAT16_THRESHOLD)
501  fprintf(stderr, "Warning: Filesystem is FAT32 according to fat_length "
502  "and fat32_length fields,\n"
503  " but has only %lu clusters, less than the required "
504  "minimum of %d.\n"
505  " This may lead to problems on some systems.\n",
506  (unsigned long)fs->data_clusters, FAT16_THRESHOLD);
507 
508  fs->backupboot_start = le16toh(b.backup_boot) * logical_sector_size;
509  check_backup_boot(fs, &b, logical_sector_size);
510 
511  read_fsinfo(fs, &b, logical_sector_size);
512  } else if (!atari_format) {
513  /* On real MS-DOS, a 16 bit FAT is used whenever there would be too
514  * much clusers otherwise. */
515  fs->fat_bits = (fs->data_clusters >= FAT12_THRESHOLD) ? 16 : 12;
516  if (fs->data_clusters >= FAT16_THRESHOLD)
517  die("Too many clusters (%lu) for FAT16 filesystem.",
518  (unsigned long)fs->data_clusters);
519  } else {
520  /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs
521  * on floppies, and always 16 bit on harddisks. */
522  fs->fat_bits = 16; /* assume 16 bit FAT for now */
523  /* If more clusters than fat entries in 16-bit fat, we assume
524  * it's a real MSDOS FS with 12-bit fat. */
525  if (fs->data_clusters + 2 > fat_length * logical_sector_size * 8 / 16 ||
526  /* if it has one of the usual floppy sizes -> 12bit FAT */
527  (total_sectors == 720 || total_sectors == 1440 ||
528  total_sectors == 2880))
529  fs->fat_bits = 12;
530  }
531  /* On FAT32, the high 4 bits of a FAT entry are reserved */
532  fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits;
533  position = fat_length * logical_sector_size;
534  if (position > OFF_MAX)
535  die("Filesystem is too large.");
536  fs->fat_size = position;
537 
538  fs->label[0] = 0;
539  if (fs->fat_bits == 12 || fs->fat_bits == 16) {
540  struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b;
541  if (b16->extended_sig == 0x29) {
542  memmove(fs->label, b16->label, 11);
543  fs->serial = b16->serial;
544  }
545  } else if (fs->fat_bits == 32) {
546  if (b.extended_sig == 0x29) {
547  memmove(fs->label, &b.label, 11);
548  fs->serial = b.serial;
549  }
550  }
551 
552  position = (long long)fs->fat_size * 8 / fs->fat_bits;
553  if (position > UINT_MAX)
554  die("FAT has space for too many entries (%lld).", (long long)position);
555  total_fat_entries = position;
556  if (fs->data_clusters > total_fat_entries - 2)
557  die("Filesystem has %u clusters but only space for %u FAT entries.",
558  fs->data_clusters, total_fat_entries - 2);
559  if (!fs->root_entries && !fs->root_cluster)
560  die("Root directory has zero size.");
561  if (fs->root_entries & (MSDOS_DPS - 1))
562  die("Root directory (%d entries) doesn't span an integral number of "
563  "sectors.", fs->root_entries);
564  if (logical_sector_size & (SECTOR_SIZE - 1))
565  die("Logical sector size (%u bytes) is not a multiple of the physical "
566  "sector size.", logical_sector_size);
567 #if 0 /* linux kernel doesn't check that either */
568  /* ++roman: On Atari, these two fields are often left uninitialized */
569  if (!atari_format && (!b.secs_track || !b.heads))
570  die("Invalid disk format in boot sector.");
571 #endif
572  if (verbose)
573  dump_boot(fs, &b, logical_sector_size);
574 }
575 
576 static void write_boot_label_or_serial(int label_mode, DOS_FS * fs,
577  const char *label, uint32_t serial)
578 {
579  if (fs->fat_bits == 12 || fs->fat_bits == 16) {
580  struct boot_sector_16 b16;
581 
582  fs_read(0, sizeof(b16), &b16);
583  if (b16.extended_sig != 0x29) {
584  b16.extended_sig = 0x29;
585  b16.serial = 0;
586  memmove(b16.label, "NO NAME ", 11);
587  memmove(b16.fs_type, fs->fat_bits == 12 ? "FAT12 " : "FAT16 ",
588  8);
589  }
590 
591  if (label_mode)
592  memmove(b16.label, label, 11);
593  else
594  b16.serial = serial;
595 
596  fs_write(0, sizeof(b16), &b16);
597  } else if (fs->fat_bits == 32) {
598  struct boot_sector b;
599 
600  fs_read(0, sizeof(b), &b);
601  if (b.extended_sig != 0x29) {
602  b.extended_sig = 0x29;
603  b.serial = 0;
604  memmove(b.label, "NO NAME ", 11);
605  memmove(b.fs_type, "FAT32 ", 8);
606  }
607 
608  if (label_mode)
609  memmove(b.label, label, 11);
610  else
611  b.serial = serial;
612 
613  fs_write(0, sizeof(b), &b);
614  if (fs->backupboot_start)
615  fs_write(fs->backupboot_start, sizeof(b), &b);
616  }
617 }
618 
619 void write_boot_label(DOS_FS * fs, const char *label)
620 {
622 }
623 
624 void write_serial(DOS_FS * fs, uint32_t serial)
625 {
626  write_boot_label_or_serial(0, fs, NULL, serial);
627 }
628 
629 off_t find_volume_de(DOS_FS * fs, DIR_ENT * de)
630 {
631  uint32_t cluster;
632  off_t offset;
633  int i;
634 
635  if (fs->root_cluster) {
636  for (cluster = fs->root_cluster;
637  cluster != 0 && cluster != -1;
638  cluster = next_cluster(fs, cluster)) {
639  offset = cluster_start(fs, cluster);
640  for (i = 0; i * sizeof(DIR_ENT) < fs->cluster_size; i++) {
641  fs_read(offset, sizeof(DIR_ENT), de);
642 
643  /* no point in scanning after end of directory marker */
644  if (!de->name[0])
645  return 0;
646 
647  if (!IS_FREE(de->name) &&
648  de->attr != VFAT_LN_ATTR && de->attr & ATTR_VOLUME)
649  return offset;
650  offset += sizeof(DIR_ENT);
651  }
652  }
653  } else {
654  for (i = 0; i < fs->root_entries; i++) {
655  offset = fs->root_start + i * sizeof(DIR_ENT);
656  fs_read(offset, sizeof(DIR_ENT), de);
657 
658  /* no point in scanning after end of directory marker */
659  if (!de->name[0])
660  return 0;
661 
662  if (!IS_FREE(de->name) &&
663  de->attr != VFAT_LN_ATTR && de->attr & ATTR_VOLUME)
664  return offset;
665  }
666  }
667 
668  return 0;
669 }
670 
671 void write_volume_label(DOS_FS * fs, char *label)
672 {
673  time_t now;
674  struct tm *mtime;
675  off_t offset;
676  int created;
677  DIR_ENT de;
678 
679  created = 0;
680  offset = find_volume_de(fs, &de);
681  if (offset == 0) {
682  created = 1;
683  offset = alloc_rootdir_entry(fs, &de, label, 0);
684  }
685 
686  memcpy(de.name, label, 11);
687  if (de.name[0] == 0xe5)
688  de.name[0] = 0x05;
689 
690  now = time(NULL);
691  mtime = (now != (time_t)-1) ? localtime(&now) : NULL;
692  if (mtime && mtime->tm_year >= 80 && mtime->tm_year <= 207) {
693  de.time = htole16((unsigned short)((mtime->tm_sec >> 1) +
694  (mtime->tm_min << 5) +
695  (mtime->tm_hour << 11)));
696  de.date = htole16((unsigned short)(mtime->tm_mday +
697  ((mtime->tm_mon + 1) << 5) +
698  ((mtime->tm_year - 80) << 9)));
699  } else {
700  /* fallback to 1.1.1980 00:00:00 */
701  de.time = htole16(0);
702  de.date = htole16(1 + (1 << 5));
703  }
704  if (created) {
705  de.attr = ATTR_VOLUME;
706  de.ctime_ms = 0;
707  de.ctime = de.time;
708  de.cdate = de.date;
709  de.adate = de.date;
710  de.starthi = 0;
711  de.start = 0;
712  de.size = 0;
713  }
714 
715  fs_write(offset, sizeof(DIR_ENT), &de);
716 }
717 
718 void write_label(DOS_FS * fs, char *label)
719 {
720  int l = strlen(label);
721 
722  while (l < 11)
723  label[l++] = ' ';
724 
725  write_boot_label(fs, label);
726  write_volume_label(fs, label);
727 }
728 
730 {
731  off_t offset;
732  DIR_ENT de;
733 
734  write_boot_label(fs, "NO NAME ");
735 
736  offset = find_volume_de(fs, &de);
737  if (offset) {
738  /* mark entry as deleted */
739  de.name[0] = 0xe5;
740  /* remove ATTR_VOLUME for compatibility with older fatlabel version
741  * which ignores above deletion mark for entries with ATTR_VOLUME */
742  de.attr = 0;
743  fs_write(offset, sizeof(DIR_ENT), &de);
744  }
745 }
746 
747 const char *pretty_label(const char *label)
748 {
749  static char buffer[256];
750  char *p;
751  int i;
752  int last;
753 
754  for (last = 10; last >= 0; last--) {
755  if (label[last] != ' ')
756  break;
757  }
758 
759  p = buffer;
760  for (i = 0; i <= last && label[i] && p < buffer + sizeof(buffer) - 1; ++i) {
761  if (!dos_char_to_printable(&p, label[i], buffer + sizeof(buffer) - 1 - p))
762  *p++ = '_';
763  }
764  *p = 0;
765 
766  return buffer;
767 }
void write_label(DOS_FS *fs, char *label)
Definition: boot.c:718
#define FAT16_THRESHOLD
Definition: boot.c:50
static void read_fsinfo(DOS_FS *fs, struct boot_sector *b, unsigned int lss)
Definition: boot.c:347
static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, unsigned int lss)
Definition: boot.c:262
const char * pretty_label(const char *label)
Definition: boot.c:747
static void init_fsinfo_except_reserved(struct info_sector *i)
Definition: boot.c:338
#define FAT12_THRESHOLD
Definition: boot.c:49
#define ROUND_TO_MULTIPLE(n, m)
Definition: boot.c:45
off_t find_volume_de(DOS_FS *fs, DIR_ENT *de)
Definition: boot.c:629
static void write_boot_label_or_serial(int label_mode, DOS_FS *fs, const char *label, uint32_t serial)
Definition: boot.c:576
void write_volume_label(DOS_FS *fs, char *label)
Definition: boot.c:671
#define GET_UNALIGNED_W(f)
Definition: boot.c:195
static const char * get_media_descr(unsigned char media)
Definition: boot.c:198
void remove_label(DOS_FS *fs)
Definition: boot.c:729
void read_boot(DOS_FS *fs)
Definition: boot.c:415
off_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern, int gen_name)
Definition: boot.c:52
uint8_t media
Definition: boot.c:179
void write_serial(DOS_FS *fs, uint32_t serial)
Definition: boot.c:624
const char * descr
Definition: boot.c:180
static void dump_boot(DOS_FS *fs, struct boot_sector *b, unsigned lss)
Definition: boot.c:209
void write_boot_label(DOS_FS *fs, const char *label)
Definition: boot.c:619
static struct @0 mediabytes[]
int dos_char_to_printable(char **p, unsigned char c, unsigned int out_size)
Definition: charconv.c:353
static DOS_FILE * root
Definition: check.c:51
void die(const char *msg,...)
Definition: common.c:53
void * alloc(int size)
Definition: common.c:81
int atari_format
Definition: common.c:44
int get_choice(int noninteractive_result, const char *noninteractive_msg, int choices,...)
Definition: common.c:157
#define OFF_MAX
Definition: common.h:32
uint32_t next_cluster(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:355
void set_owner(DOS_FS *fs, uint32_t cluster, DOS_FILE *owner)
Definition: fat.c:383
off_t cluster_start(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:368
DOS_FILE * get_owner(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:394
void get_fat(FAT_ENTRY *entry, void *fat, uint32_t cluster, DOS_FS *fs)
Definition: fat.c:48
void set_fat(DOS_FS *fs, uint32_t cluster, int32_t new)
Definition: fat.c:268
int verbose
Definition: fatlabel.c:49
unsigned n_files
Definition: fatlabel.c:51
#define VFAT_LN_ATTR
Definition: fsck.fat.h:39
static CHANGE * last
Definition: io.c:55
int fs_test(off_t pos, int size)
Definition: io.c:101
void fs_read(off_t pos, int size, void *data)
Definition: io.c:78
void fs_write(off_t pos, int size, void *data)
Definition: io.c:114
static int backup_boot
Definition: mkfs.fat.c:242
#define MSDOS_DPS
Definition: msdos_fs.h:26
#define SECTOR_SIZE
Definition: msdos_fs.h:25
#define IS_FREE(n)
Definition: msdos_fs.h:42
#define MSDOS_DIR_BITS
Definition: msdos_fs.h:28
#define ATTR_VOLUME
Definition: msdos_fs.h:34
#define MSDOS_NAME
Definition: msdos_fs.h:44
uint16_t cdate
Definition: fsck.fat.h:135
uint16_t time
Definition: fsck.fat.h:138
uint16_t start
Definition: fsck.fat.h:138
uint16_t ctime
Definition: fsck.fat.h:134
uint16_t starthi
Definition: fsck.fat.h:137
uint32_t size
Definition: fsck.fat.h:139
uint8_t attr
Definition: fsck.fat.h:131
uint8_t ctime_ms
Definition: fsck.fat.h:133
uint16_t date
Definition: fsck.fat.h:138
uint16_t adate
Definition: fsck.fat.h:136
uint8_t name[11]
Definition: fsck.fat.h:130
unsigned int fat_bits
Definition: fsck.fat.h:161
unsigned int cluster_size
Definition: fsck.fat.h:167
unsigned int fat_size
Definition: fsck.fat.h:160
off_t backupboot_start
Definition: fsck.fat.h:171
off_t fsinfo_start
Definition: fsck.fat.h:169
int nfats
Definition: fsck.fat.h:158
unsigned int eff_fat_bits
Definition: fsck.fat.h:162
off_t fat_start
Definition: fsck.fat.h:159
uint32_t data_clusters
Definition: fsck.fat.h:168
unsigned int root_entries
Definition: fsck.fat.h:165
uint32_t root_cluster
Definition: fsck.fat.h:163
unsigned char * fat
Definition: fsck.fat.h:172
off_t root_start
Definition: fsck.fat.h:164
off_t data_start
Definition: fsck.fat.h:166
long free_clusters
Definition: fsck.fat.h:170
char label[11]
Definition: fsck.fat.h:175
uint32_t serial
Definition: fsck.fat.h:174
Definition: fsck.fat.h:152
uint32_t value
Definition: fsck.fat.h:153
uint8_t fs_type[8]
Definition: fsck.fat.h:113
uint8_t extended_sig
Definition: fsck.fat.h:110
uint8_t label[11]
Definition: fsck.fat.h:112
uint32_t serial
Definition: fsck.fat.h:111
uint16_t backup_boot
Definition: fsck.fat.h:75
uint8_t fs_type[8]
Definition: fsck.fat.h:84
uint8_t sector_size[2]
Definition: fsck.fat.h:56
uint32_t serial
Definition: fsck.fat.h:82
uint8_t dir_entries[2]
Definition: fsck.fat.h:60
uint32_t fat32_length
Definition: fsck.fat.h:70
uint32_t total_sect
Definition: fsck.fat.h:67
uint16_t secs_track
Definition: fsck.fat.h:64
uint16_t info_sector
Definition: fsck.fat.h:74
uint8_t extended_sig
Definition: fsck.fat.h:81
uint16_t reserved
Definition: fsck.fat.h:58
uint8_t media
Definition: fsck.fat.h:62
uint8_t fats
Definition: fsck.fat.h:59
uint16_t fat_length
Definition: fsck.fat.h:63
uint8_t label[11]
Definition: fsck.fat.h:83
uint8_t cluster_size
Definition: fsck.fat.h:57
uint32_t hidden
Definition: fsck.fat.h:66
uint8_t sectors[2]
Definition: fsck.fat.h:61
uint8_t system_id[8]
Definition: fsck.fat.h:54
uint16_t heads
Definition: fsck.fat.h:65
uint32_t root_cluster
Definition: fsck.fat.h:73
uint32_t boot_sign
Definition: fsck.fat.h:126
uint32_t magic
Definition: fsck.fat.h:120
uint32_t signature
Definition: fsck.fat.h:122
uint32_t next_cluster
Definition: fsck.fat.h:124
uint32_t free_clusters
Definition: fsck.fat.h:123