- // doslabel.c -- read/set the volume labels of DOS partitions by Pierre-Marie Baty <pm@pmbaty.com> 
-   
- #include <stdio.h> 
- #include <stdlib.h> 
- #include <string.h> 
- #include <errno.h> 
- #include <ctype.h> 
-   
-   
- int main (int argc, char **argv) 
- { 
-         // program entrypoint 
-   
-         typedef struct __attribute__((packed)) fatfs_header_s 
-         { 
-                 unsigned char bootstrap_code[3]; // offset 0 
-                 char oem_name_and_version[8]; // offset 3 
-                 unsigned short bytes_per_sector; // offset 11 
-                 unsigned char sectors_per_cluster; // offset 13 
-                 unsigned short reserved_sectors; // offset 14 
-                 unsigned char fat_copies; // offset 16 
-                 unsigned short rootdir_entries; // offset 17 
-                 unsigned short total_sectors; // offset 19 
-                 unsigned char media_type; // offset 21 
-                 unsigned short sectors_per_fat; // offset 22 
-                 unsigned short sectors_per_track; // offset 24 
-                 unsigned short heads; // offset 26 
-                 unsigned short hidden_sectors; // offset 28; 
-         } fatfs_header_t; 
-   
-         unsigned char first_sector[512]; 
-         fatfs_header_t *fat_header; 
-         const char *dev_pathname; 
-         size_t label_offset; 
-         size_t char_index; 
-         char *new_label; 
-         char label[12]; 
-         FILE *fp; 
-   
-         // consistency checks 
-         if ((argc < 2) || (*(argv[1]) == '-')) 
-         { 
-                 fprintf (- stderr , "usage: doslabel <device> [new-label]\n");
 
-         } 
-   
-         dev_pathname = argv[1]; // read arguments 
-         new_label = (argc > 2 ? argv[2] : NULL); 
-   
-         // open and read the first sector of the passed device pathname 
-         if (((- fp  = fopen (- dev_pathname , "r+b")) ==-  NULL ) || (fread (- first_sector , 512, 1,-  fp ) != 1))
 
-         { 
-                 fprintf (- stderr , "error: can't read first sector of %s: %s\n",-  dev_pathname , strerror (- errno ));
 
-         } 
-   
-         // consistency checks 
-         fat_header = (fatfs_header_t *) first_sector; 
-   
-         // is it a FAT12/FAT16 or FAT32 BPB ? 
-         if ((memcmp (&- first_sector [510], "\x55\xaa", 2) == 0)
 
-             && (   (fat_header->bytes_per_sector == 512) 
-                 || (fat_header->bytes_per_sector == 1024) 
-                 || (fat_header->bytes_per_sector == 2048) 
-                 || (fat_header->bytes_per_sector == 4096)) 
-             && (   (fat_header->sectors_per_cluster == 1) 
-                 || (fat_header->sectors_per_cluster == 2) 
-                 || (fat_header->sectors_per_cluster == 4) 
-                 || (fat_header->sectors_per_cluster == 8) 
-                 || (fat_header->sectors_per_cluster == 16) 
-                 || (fat_header->sectors_per_cluster == 32) 
-                 || (fat_header->sectors_per_cluster == 64) 
-                 || (fat_header->sectors_per_cluster == 128)) 
-             && (   (fat_header->reserved_sectors == 1) 
-                 || (fat_header->reserved_sectors == 32))) 
-                 label_offset = (fat_header->sectors_per_fat != 0 ? 43 : 71); 
-         else 
-         { 
-                 // volume labels in exFAT filesystems are actually directory entries with a special flag 
-                 // we don't support that at the moment (FIXME) 
-                 // that's fine, because EFI partitions can't be exFAT -- only FAT12/16. 
-                 fprintf (- stderr , "error: only FAT12/FAT16/FAT32 filesystems are supported\n");
 
-         } 
-   
-         // do we want to read or set the volume label ? 
-         if (new_label == NULL) 
-         { 
-                 // read the label and strip it from trailing spaces 
-                 memcpy (- label , &- first_sector [- label_offset ], 11);
 
-                 label[11] = 0; 
-                 for (char_index = 10; char_index > 0; char_index--) 
-                         if (label[char_index] == ' ') 
-                                 label[char_index] = 0; 
-                         else 
-                                 break; 
-                 if (label[char_index] == ' ') 
-                         label[char_index] = 0; 
-   
-                 // print it to the standard output 
-         } 
-         else if (argc == 3) 
-         { 
-                 // write a new DOS partition label 
-                 fseek (- fp ,-  label_offset ,-  SEEK_SET ); // can't fail
 
-                 memset (- label , ' ', sizeof (- label ));
 
-                 if (fwrite (- label , 11, 1,-  fp ) != 1)
 
-                 { 
-                         fprintf (- stderr , "error: can't write new volume label to %s: %s\n",-  dev_pathname , strerror (- errno ));
 
-                 } 
-         } 
-   
- } 
-