Subversion Repositories QNX 8.QNX8 utilities

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
// doslabel.c -- read/set the volume labels of DOS partitions by Pierre-Marie Baty <pm@pmbaty.com>
2
 
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
#include <errno.h>
7
#include <ctype.h>
8
 
9
 
10
int main (int argc, char **argv)
11
{
12
        // program entrypoint
13
 
14
        typedef struct __attribute__((packed)) fatfs_header_s
15
        {
16
                unsigned char bootstrap_code[3]; // offset 0
17
                char oem_name_and_version[8]; // offset 3
18
                unsigned short bytes_per_sector; // offset 11
19
                unsigned char sectors_per_cluster; // offset 13
20
                unsigned short reserved_sectors; // offset 14
21
                unsigned char fat_copies; // offset 16
22
                unsigned short rootdir_entries; // offset 17
23
                unsigned short total_sectors; // offset 19
24
                unsigned char media_type; // offset 21
25
                unsigned short sectors_per_fat; // offset 22
26
                unsigned short sectors_per_track; // offset 24
27
                unsigned short heads; // offset 26
28
                unsigned short hidden_sectors; // offset 28;
29
        } fatfs_header_t;
30
 
31
        unsigned char first_sector[512];
32
        fatfs_header_t *fat_header;
33
        const char *dev_pathname;
34
        size_t label_offset;
35
        size_t char_index;
36
        char *new_label;
37
        char label[12];
38
        FILE *fp;
39
 
40
        // consistency checks
41
        if ((argc < 2) || (*(argv[1]) == '-'))
42
        {
43
                fprintf (stderr, "usage: doslabel <device> [new-label]\n");
44
                exit (1);
45
        }
46
 
47
        dev_pathname = argv[1]; // read arguments
48
        new_label = (argc > 2 ? argv[2] : NULL);
49
 
50
        // open and read the first sector of the passed device pathname
51
        if (((fp = fopen (dev_pathname, "r+b")) == NULL) || (fread (first_sector, 512, 1, fp) != 1))
52
        {
53
                fprintf (stderr, "error: can't read first sector of %s: %s\n", dev_pathname, strerror (errno));
54
                exit (1);
55
        }
56
 
57
        // consistency checks
58
        fat_header = (fatfs_header_t *) first_sector;
59
 
60
        // is it a FAT12/FAT16 or FAT32 BPB ?
61
        if ((memcmp (&first_sector[510], "\x55\xaa", 2) == 0)
62
            && (   (fat_header->bytes_per_sector == 512)
63
                || (fat_header->bytes_per_sector == 1024)
64
                || (fat_header->bytes_per_sector == 2048)
65
                || (fat_header->bytes_per_sector == 4096))
66
            && (   (fat_header->sectors_per_cluster == 1)
67
                || (fat_header->sectors_per_cluster == 2)
68
                || (fat_header->sectors_per_cluster == 4)
69
                || (fat_header->sectors_per_cluster == 8)
70
                || (fat_header->sectors_per_cluster == 16)
71
                || (fat_header->sectors_per_cluster == 32)
72
                || (fat_header->sectors_per_cluster == 64)
73
                || (fat_header->sectors_per_cluster == 128))
74
            && (   (fat_header->reserved_sectors == 1)
75
                || (fat_header->reserved_sectors == 32)))
76
                label_offset = (fat_header->sectors_per_fat != 0 ? 43 : 71);
77
        else
78
        {
79
                // volume labels in exFAT filesystems are actually directory entries with a special flag
80
                // we don't support that at the moment (FIXME)
81
                // that's fine, because EFI partitions can't be exFAT -- only FAT12/16.
82
                fprintf (stderr, "error: only FAT12/FAT16/FAT32 filesystems are supported\n");
83
                exit (1);
84
        }
85
 
86
        // do we want to read or set the volume label ?
87
        if (new_label == NULL)
88
        {
89
                // read the label and strip it from trailing spaces
90
                memcpy (label, &first_sector[label_offset], 11);
91
                label[11] = 0;
92
                for (char_index = 10; char_index > 0; char_index--)
93
                        if (label[char_index] == ' ')
94
                                label[char_index] = 0;
95
                        else
96
                                break;
97
                if (label[char_index] == ' ')
98
                        label[char_index] = 0;
99
 
100
                // print it to the standard output
101
                printf ("%s\n", label);
102
        }
103
        else if (argc == 3)
104
        {
105
                // write a new DOS partition label
106
                fseek (fp, label_offset, SEEK_SET); // can't fail
107
                memset (label, ' ', sizeof (label));
108
                memcpy (label, new_label, strlen (new_label));
109
                if (fwrite (label, 11, 1, fp) != 1)
110
                {
111
                        fprintf (stderr, "error: can't write new volume label to %s: %s\n", dev_pathname, strerror (errno));
112
                        exit (1);
113
                }
114
        }
115
 
116
        fclose (fp);
117
        exit (0);
118
}