~ubuntu-branches/ubuntu/saucy/dosfstools/saucy-proposed

« back to all changes in this revision

Viewing changes to src/boot.c

  • Committer: Package Import Robot
  • Author(s): Steve Langasek
  • Date: 2011-12-19 15:25:47 UTC
  • mfrom: (4.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20111219152547-ynwswo9ubk6l6szm
Tags: 3.0.12-1ubuntu1
* Merge from Debian testing, remaining changes:
  - debian/patches/02_fat32_label.patch: resolve an error thrown by
    dosfslabel when trying to label.
* Dropped changes, superseded in Debian:
  - build-depend on quilt: Debian is source format 3.0 (quilt).
  - debian/patches/01_fix_sector_count.patch: included upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include "io.h"
36
36
#include "boot.h"
37
37
 
38
 
 
39
38
#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
40
39
    /* don't divide by zero */
41
40
 
47
46
    __u8 media;
48
47
    char *descr;
49
48
} mediabytes[] = {
50
 
    { 0xf0, "5.25\" or 3.5\" HD floppy" },
51
 
    { 0xf8, "hard disk" },
52
 
    { 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or "
53
 
            "5.25\" 1.2M floppy 2s/80tr/15sec" },
54
 
    { 0xfa, "5.25\" 320k floppy 1s/80tr/8sec" },
55
 
    { 0xfb, "3.5\" 640k floppy 2s/80tr/8sec" },
56
 
    { 0xfc, "5.25\" 180k floppy 1s/40tr/9sec" },
57
 
    { 0xfd, "5.25\" 360k floppy 2s/40tr/9sec" },
58
 
    { 0xfe, "5.25\" 160k floppy 1s/40tr/8sec" },
59
 
    { 0xff, "5.25\" 320k floppy 2s/40tr/8sec" },
60
 
};
 
49
    {
 
50
    0xf0, "5.25\" or 3.5\" HD floppy"}, {
 
51
    0xf8, "hard disk"}, {
 
52
    0xf9, "3,5\" 720k floppy 2s/80tr/9sec or "
 
53
            "5.25\" 1.2M floppy 2s/80tr/15sec"}, {
 
54
    0xfa, "5.25\" 320k floppy 1s/80tr/8sec"}, {
 
55
    0xfb, "3.5\" 640k floppy 2s/80tr/8sec"}, {
 
56
    0xfc, "5.25\" 180k floppy 1s/40tr/9sec"}, {
 
57
    0xfd, "5.25\" 360k floppy 2s/40tr/9sec"}, {
 
58
    0xfe, "5.25\" 160k floppy 1s/40tr/8sec"}, {
 
59
0xff, "5.25\" 320k floppy 2s/40tr/8sec"},};
61
60
 
62
 
#if defined __alpha || defined __arm || defined __ia64__ || defined __s390x__ \
63
 
 || defined __x86_64__ || defined __ppc64__ || defined __bfin__ \
64
 
 || defined __MICROBLAZE__
 
61
#if defined __alpha || defined __arm || defined __arm__ || defined __ia64__ || defined __x86_64__ \
 
62
 || defined __ppc64__ || defined __bfin__ || defined __MICROBLAZE__
65
63
/* Unaligned fields must first be copied byte-wise */
66
64
#define GET_UNALIGNED_W(f)                      \
67
65
    ({                                          \
73
71
#define GET_UNALIGNED_W(f) CF_LE_W( *(unsigned short *)&f )
74
72
#endif
75
73
 
76
 
 
77
 
static char *get_media_descr( unsigned char media )
 
74
static char *get_media_descr(unsigned char media)
78
75
{
79
76
    int i;
80
77
 
81
 
    for( i = 0; i < sizeof(mediabytes)/sizeof(*mediabytes); ++i ) {
 
78
    for (i = 0; i < sizeof(mediabytes) / sizeof(*mediabytes); ++i) {
82
79
        if (mediabytes[i].media == media)
83
 
            return( mediabytes[i].descr );
 
80
            return (mediabytes[i].descr);
84
81
    }
85
 
    return( "undefined" );
 
82
    return ("undefined");
86
83
}
87
84
 
88
 
static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss)
 
85
static void dump_boot(DOS_FS * fs, struct boot_sector *b, unsigned lss)
89
86
{
90
87
    unsigned short sectors;
91
88
 
92
89
    printf("Boot sector contents:\n");
93
90
    if (!atari_format) {
94
91
        char id[9];
95
 
        strncpy(id,b->system_id,8);
 
92
        strncpy(id, (const char *)b->system_id, 8);
96
93
        id[8] = 0;
97
 
        printf("System ID \"%s\"\n",id);
98
 
    }
99
 
    else {
 
94
        printf("System ID \"%s\"\n", id);
 
95
    } else {
100
96
        /* On Atari, a 24 bit serial number is stored at offset 8 of the boot
101
97
         * sector */
102
98
        printf("Serial number 0x%x\n",
103
 
               b->system_id[5] | (b->system_id[6]<<8) | (b->system_id[7]<<16));
 
99
               b->system_id[5] | (b->
 
100
                                  system_id[6] << 8) | (b->system_id[7] << 16));
104
101
    }
105
 
    printf("Media byte 0x%02x (%s)\n",b->media,get_media_descr(b->media));
106
 
    printf("%10d bytes per logical sector\n",GET_UNALIGNED_W(b->sector_size));
107
 
    printf("%10d bytes per cluster\n",fs->cluster_size);
108
 
    printf("%10d reserved sector%s\n",CF_LE_W(b->reserved),
 
102
    printf("Media byte 0x%02x (%s)\n", b->media, get_media_descr(b->media));
 
103
    printf("%10d bytes per logical sector\n", GET_UNALIGNED_W(b->sector_size));
 
104
    printf("%10d bytes per cluster\n", fs->cluster_size);
 
105
    printf("%10d reserved sector%s\n", CF_LE_W(b->reserved),
109
106
           CF_LE_W(b->reserved) == 1 ? "" : "s");
110
107
    printf("First FAT starts at byte %llu (sector %llu)\n",
111
108
           (unsigned long long)fs->fat_start,
112
 
           (unsigned long long)fs->fat_start/lss);
113
 
    printf("%10d FATs, %d bit entries\n",b->fats,fs->fat_bits);
114
 
    printf("%10d bytes per FAT (= %u sectors)\n",fs->fat_size,
115
 
           fs->fat_size/lss);
 
109
           (unsigned long long)fs->fat_start / lss);
 
110
    printf("%10d FATs, %d bit entries\n", b->fats, fs->fat_bits);
 
111
    printf("%10d bytes per FAT (= %u sectors)\n", fs->fat_size,
 
112
           fs->fat_size / lss);
116
113
    if (!fs->root_cluster) {
117
114
        printf("Root directory starts at byte %llu (sector %llu)\n",
118
115
               (unsigned long long)fs->root_start,
119
 
               (unsigned long long)fs->root_start/lss);
120
 
        printf("%10d root directory entries\n",fs->root_entries);
121
 
    }
122
 
    else {
123
 
        printf( "Root directory start at cluster %lu (arbitrary size)\n",
124
 
                fs->root_cluster);
 
116
               (unsigned long long)fs->root_start / lss);
 
117
        printf("%10d root directory entries\n", fs->root_entries);
 
118
    } else {
 
119
        printf("Root directory start at cluster %lu (arbitrary size)\n",
 
120
               fs->root_cluster);
125
121
    }
126
122
    printf("Data area starts at byte %llu (sector %llu)\n",
127
123
           (unsigned long long)fs->data_start,
128
 
           (unsigned long long)fs->data_start/lss);
129
 
    printf("%10lu data clusters (%llu bytes)\n",fs->clusters,
130
 
           (unsigned long long)fs->clusters*fs->cluster_size);
131
 
    printf("%u sectors/track, %u heads\n",CF_LE_W(b->secs_track),
 
124
           (unsigned long long)fs->data_start / lss);
 
125
    printf("%10lu data clusters (%llu bytes)\n", fs->clusters,
 
126
           (unsigned long long)fs->clusters * fs->cluster_size);
 
127
    printf("%u sectors/track, %u heads\n", CF_LE_W(b->secs_track),
132
128
           CF_LE_W(b->heads));
133
 
    printf("%10u hidden sectors\n",
134
 
           atari_format ?
 
129
    printf("%10u hidden sectors\n", atari_format ?
135
130
           /* On Atari, the hidden field is only 16 bit wide and unused */
136
131
           (((unsigned char *)&b->hidden)[0] |
137
 
            ((unsigned char *)&b->hidden)[1] << 8) :
138
 
           CF_LE_L(b->hidden));
139
 
    sectors = GET_UNALIGNED_W( b->sectors );
 
132
            ((unsigned char *)&b->hidden)[1] << 8) : CF_LE_L(b->hidden));
 
133
    sectors = GET_UNALIGNED_W(b->sectors);
140
134
    printf("%10u sectors total\n", sectors ? sectors : CF_LE_L(b->total_sect));
141
135
}
142
136
 
143
 
static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss)
 
137
static void check_backup_boot(DOS_FS * fs, struct boot_sector *b, int lss)
144
138
{
145
139
    struct boot_sector b2;
146
140
 
147
141
    if (!fs->backupboot_start) {
148
 
        printf( "There is no backup boot sector.\n" );
 
142
        printf("There is no backup boot sector.\n");
149
143
        if (CF_LE_W(b->reserved) < 3) {
150
 
            printf( "And there is no space for creating one!\n" );
 
144
            printf("And there is no space for creating one!\n");
151
145
            return;
152
146
        }
153
147
        if (interactive)
154
 
            printf( "1) Create one\n2) Do without a backup\n" );
155
 
        else printf( "  Auto-creating backup boot block.\n" );
156
 
        if (!interactive || get_key("12","?") == '1') {
 
148
            printf("1) Create one\n2) Do without a backup\n");
 
149
        else
 
150
            printf("  Auto-creating backup boot block.\n");
 
151
        if (!interactive || get_key("12", "?") == '1') {
157
152
            int bbs;
158
153
            /* The usual place for the backup boot sector is sector 6. Choose
159
154
             * that or the last reserved sector. */
162
157
            else {
163
158
                bbs = CF_LE_W(b->reserved) - 1;
164
159
                if (bbs == CF_LE_W(b->info_sector))
165
 
                    --bbs; /* this is never 0, as we checked reserved >= 3! */
 
160
                    --bbs;      /* this is never 0, as we checked reserved >= 3! */
166
161
            }
167
 
            fs->backupboot_start = bbs*lss;
 
162
            fs->backupboot_start = bbs * lss;
168
163
            b->backup_boot = CT_LE_W(bbs);
169
 
            fs_write(fs->backupboot_start,sizeof(*b),b);
170
 
            fs_write((loff_t)offsetof(struct boot_sector,backup_boot),
171
 
                     sizeof(b->backup_boot),&b->backup_boot);
172
 
            printf( "Created backup of boot sector in sector %d\n", bbs );
173
 
            return;
174
 
        }
175
 
        else return;
 
164
            fs_write(fs->backupboot_start, sizeof(*b), b);
 
165
            fs_write((loff_t) offsetof(struct boot_sector, backup_boot),
 
166
                     sizeof(b->backup_boot), &b->backup_boot);
 
167
            printf("Created backup of boot sector in sector %d\n", bbs);
 
168
            return;
 
169
        } else
 
170
            return;
176
171
    }
177
172
 
178
 
    fs_read(fs->backupboot_start,sizeof(b2),&b2);
179
 
    if (memcmp(b,&b2,sizeof(b2)) != 0) {
 
173
    fs_read(fs->backupboot_start, sizeof(b2), &b2);
 
174
    if (memcmp(b, &b2, sizeof(b2)) != 0) {
180
175
        /* there are any differences */
181
176
        __u8 *p, *q;
182
177
        int i, pos, first = 1;
183
178
        char buf[20];
184
179
 
185
 
        printf( "There are differences between boot sector and its backup.\n" );
186
 
        printf( "Differences: (offset:original/backup)\n  " );
 
180
        printf("There are differences between boot sector and its backup.\n");
 
181
        printf("Differences: (offset:original/backup)\n  ");
187
182
        pos = 2;
188
 
        for( p = (__u8 *)b, q = (__u8 *)&b2, i = 0; i < sizeof(b2);
189
 
             ++p, ++q, ++i ) {
 
183
        for (p = (__u8 *) b, q = (__u8 *) & b2, i = 0; i < sizeof(b2);
 
184
             ++p, ++q, ++i) {
190
185
            if (*p != *q) {
191
 
                sprintf( buf, "%s%u:%02x/%02x", first ? "" : ", ",
192
 
                         (unsigned)(p-(__u8 *)b), *p, *q );
193
 
                if (pos + strlen(buf) > 78) printf( "\n  " ), pos = 2;
194
 
                printf( "%s", buf );
 
186
                sprintf(buf, "%s%u:%02x/%02x", first ? "" : ", ",
 
187
                        (unsigned)(p - (__u8 *) b), *p, *q);
 
188
                if (pos + strlen(buf) > 78)
 
189
                    printf("\n  "), pos = 2;
 
190
                printf("%s", buf);
195
191
                pos += strlen(buf);
196
192
                first = 0;
197
193
            }
198
194
        }
199
 
        printf( "\n" );
 
195
        printf("\n");
200
196
 
201
197
        if (interactive)
202
 
            printf( "1) Copy original to backup\n"
203
 
                    "2) Copy backup to original\n"
204
 
                    "3) No action\n" );
205
 
        else printf( "  Not automatically fixing this.\n" );
206
 
        switch (interactive ? get_key("123","?") : '3') {
207
 
          case '1':
208
 
            fs_write(fs->backupboot_start,sizeof(*b),b);
209
 
            break;
210
 
          case '2':
211
 
            fs_write(0,sizeof(b2),&b2);
212
 
            break;
213
 
          default:
 
198
            printf("1) Copy original to backup\n"
 
199
                   "2) Copy backup to original\n" "3) No action\n");
 
200
        else
 
201
            printf("  Not automatically fixing this.\n");
 
202
        switch (interactive ? get_key("123", "?") : '3') {
 
203
        case '1':
 
204
            fs_write(fs->backupboot_start, sizeof(*b), b);
 
205
            break;
 
206
        case '2':
 
207
            fs_write(0, sizeof(b2), &b2);
 
208
            break;
 
209
        default:
214
210
            break;
215
211
        }
216
212
    }
225
221
    i->boot_sign = CT_LE_W(0xaa55);
226
222
}
227
223
 
228
 
static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss)
 
224
static void read_fsinfo(DOS_FS * fs, struct boot_sector *b, int lss)
229
225
{
230
226
    struct info_sector i;
231
227
 
232
228
    if (!b->info_sector) {
233
 
        printf( "No FSINFO sector\n" );
 
229
        printf("No FSINFO sector\n");
234
230
        if (interactive)
235
 
            printf( "1) Create one\n2) Do without FSINFO\n" );
236
 
        else printf( "  Not automatically creating it.\n" );
237
 
        if (interactive && get_key("12","?") == '1') {
 
231
            printf("1) Create one\n2) Do without FSINFO\n");
 
232
        else
 
233
            printf("  Not automatically creating it.\n");
 
234
        if (interactive && get_key("12", "?") == '1') {
238
235
            /* search for a free reserved sector (not boot sector and not
239
236
             * backup boot sector) */
240
237
            __u32 s;
241
 
            for( s = 1; s < CF_LE_W(b->reserved); ++s )
242
 
                if (s != CF_LE_W(b->backup_boot)) break;
 
238
            for (s = 1; s < CF_LE_W(b->reserved); ++s)
 
239
                if (s != CF_LE_W(b->backup_boot))
 
240
                    break;
243
241
            if (s > 0 && s < CF_LE_W(b->reserved)) {
244
242
                init_fsinfo(&i);
245
 
                fs_write((loff_t)s*lss,sizeof(i),&i);
 
243
                fs_write((loff_t) s * lss, sizeof(i), &i);
246
244
                b->info_sector = CT_LE_W(s);
247
 
                fs_write((loff_t)offsetof(struct boot_sector,info_sector),
248
 
                         sizeof(b->info_sector),&b->info_sector);
 
245
                fs_write((loff_t) offsetof(struct boot_sector, info_sector),
 
246
                         sizeof(b->info_sector), &b->info_sector);
249
247
                if (fs->backupboot_start)
250
 
                    fs_write(fs->backupboot_start+
251
 
                             offsetof(struct boot_sector,info_sector),
252
 
                             sizeof(b->info_sector),&b->info_sector);
253
 
            }
254
 
            else {
255
 
                printf( "No free reserved sector found -- "
256
 
                        "no space for FSINFO sector!\n" );
 
248
                    fs_write(fs->backupboot_start +
 
249
                             offsetof(struct boot_sector, info_sector),
 
250
                             sizeof(b->info_sector), &b->info_sector);
 
251
            } else {
 
252
                printf("No free reserved sector found -- "
 
253
                       "no space for FSINFO sector!\n");
257
254
                return;
258
255
            }
259
 
        }
260
 
        else return;
 
256
        } else
 
257
            return;
261
258
    }
262
259
 
263
 
    fs->fsinfo_start = CF_LE_W(b->info_sector)*lss;
264
 
    fs_read(fs->fsinfo_start,sizeof(i),&i);
 
260
    fs->fsinfo_start = CF_LE_W(b->info_sector) * lss;
 
261
    fs_read(fs->fsinfo_start, sizeof(i), &i);
265
262
 
266
263
    if (i.magic != CT_LE_L(0x41615252) ||
267
 
        i.signature != CT_LE_L(0x61417272) ||
268
 
        i.boot_sign != CT_LE_W(0xaa55)) {
269
 
        printf( "FSINFO sector has bad magic number(s):\n" );
 
264
        i.signature != CT_LE_L(0x61417272) || i.boot_sign != CT_LE_W(0xaa55)) {
 
265
        printf("FSINFO sector has bad magic number(s):\n");
270
266
        if (i.magic != CT_LE_L(0x41615252))
271
 
            printf( "  Offset %llu: 0x%08x != expected 0x%08x\n",
272
 
                    (unsigned long long)offsetof(struct info_sector,magic),
273
 
                    CF_LE_L(i.magic),0x41615252);
 
267
            printf("  Offset %llu: 0x%08x != expected 0x%08x\n",
 
268
                   (unsigned long long)offsetof(struct info_sector, magic),
 
269
                   CF_LE_L(i.magic), 0x41615252);
274
270
        if (i.signature != CT_LE_L(0x61417272))
275
 
            printf( "  Offset %llu: 0x%08x != expected 0x%08x\n",
276
 
                    (unsigned long long)offsetof(struct info_sector,signature),
277
 
                    CF_LE_L(i.signature),0x61417272);
 
271
            printf("  Offset %llu: 0x%08x != expected 0x%08x\n",
 
272
                   (unsigned long long)offsetof(struct info_sector, signature),
 
273
                   CF_LE_L(i.signature), 0x61417272);
278
274
        if (i.boot_sign != CT_LE_W(0xaa55))
279
 
            printf( "  Offset %llu: 0x%04x != expected 0x%04x\n",
280
 
                    (unsigned long long)offsetof(struct info_sector,boot_sign),
281
 
                    CF_LE_W(i.boot_sign),0xaa55);
 
275
            printf("  Offset %llu: 0x%04x != expected 0x%04x\n",
 
276
                   (unsigned long long)offsetof(struct info_sector, boot_sign),
 
277
                   CF_LE_W(i.boot_sign), 0xaa55);
282
278
        if (interactive)
283
 
            printf( "1) Correct\n2) Don't correct (FSINFO invalid then)\n" );
284
 
        else printf( "  Auto-correcting it.\n" );
285
 
        if (!interactive || get_key("12","?") == '1') {
 
279
            printf("1) Correct\n2) Don't correct (FSINFO invalid then)\n");
 
280
        else
 
281
            printf("  Auto-correcting it.\n");
 
282
        if (!interactive || get_key("12", "?") == '1') {
286
283
            init_fsinfo(&i);
287
 
            fs_write(fs->fsinfo_start,sizeof(i),&i);
288
 
        }
289
 
        else fs->fsinfo_start = 0;
 
284
            fs_write(fs->fsinfo_start, sizeof(i), &i);
 
285
        } else
 
286
            fs->fsinfo_start = 0;
290
287
    }
291
288
 
292
289
    if (fs->fsinfo_start)
293
290
        fs->free_clusters = CF_LE_L(i.free_clusters);
294
291
}
295
292
 
296
 
void read_boot(DOS_FS *fs)
 
293
void read_boot(DOS_FS * fs)
297
294
{
298
295
    struct boot_sector b;
299
296
    unsigned total_sectors;
301
298
    unsigned fat_length;
302
299
    loff_t data_size;
303
300
 
304
 
    fs_read(0,sizeof(b),&b);
 
301
    fs_read(0, sizeof(b), &b);
305
302
    logical_sector_size = GET_UNALIGNED_W(b.sector_size);
306
 
    if (!logical_sector_size) die("Logical sector size is zero.");
 
303
    if (!logical_sector_size)
 
304
        die("Logical sector size is zero.");
307
305
 
308
306
    /* This was moved up because it's the first thing that will fail */
309
307
    /* if the platform needs special handling of unaligned multibyte accesses */
310
308
    /* but such handling isn't being provided. See GET_UNALIGNED_W() above. */
311
 
    if (logical_sector_size & (SECTOR_SIZE-1))
 
309
    if (logical_sector_size & (SECTOR_SIZE - 1))
312
310
        die("Logical sector size (%d bytes) is not a multiple of the physical "
313
 
          "sector size.",logical_sector_size);
 
311
            "sector size.", logical_sector_size);
314
312
 
315
 
    fs->cluster_size = b.cluster_size*logical_sector_size;
316
 
    if (!fs->cluster_size) die("Cluster size is zero.");
 
313
    fs->cluster_size = b.cluster_size * logical_sector_size;
 
314
    if (!fs->cluster_size)
 
315
        die("Cluster size is zero.");
317
316
    if (b.fats != 2 && b.fats != 1)
318
 
        die("Currently, only 1 or 2 FATs are supported, not %d.\n",b.fats);
 
317
        die("Currently, only 1 or 2 FATs are supported, not %d.\n", b.fats);
319
318
    fs->nfats = b.fats;
320
319
    sectors = GET_UNALIGNED_W(b.sectors);
321
320
    total_sectors = sectors ? sectors : CF_LE_L(b.total_sect);
322
 
    if (verbose) printf("Checking we can access the last sector of the filesystem\n");
 
321
    if (verbose)
 
322
        printf("Checking we can access the last sector of the filesystem\n");
323
323
    /* Can't access last odd sector anyway, so round down */
324
 
    fs_test((loff_t)((total_sectors & ~1)-1)*(loff_t)logical_sector_size,
 
324
    fs_test((loff_t) ((total_sectors & ~1) - 1) * (loff_t) logical_sector_size,
325
325
            logical_sector_size);
326
326
    fat_length = CF_LE_W(b.fat_length) ?
327
 
                 CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length);
328
 
    fs->fat_start = (loff_t)CF_LE_W(b.reserved)*logical_sector_size;
329
 
    fs->root_start = ((loff_t)CF_LE_W(b.reserved)+b.fats*fat_length)*
330
 
      logical_sector_size;
 
327
        CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length);
 
328
    fs->fat_start = (loff_t) CF_LE_W(b.reserved) * logical_sector_size;
 
329
    fs->root_start = ((loff_t) CF_LE_W(b.reserved) + b.fats * fat_length) *
 
330
        logical_sector_size;
331
331
    fs->root_entries = GET_UNALIGNED_W(b.dir_entries);
332
 
    fs->data_start = fs->root_start+ROUND_TO_MULTIPLE(fs->root_entries <<
333
 
      MSDOS_DIR_BITS,logical_sector_size);
334
 
    data_size = (loff_t)total_sectors*logical_sector_size-fs->data_start;
335
 
    fs->clusters = data_size/fs->cluster_size;
336
 
    fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */
337
 
    fs->fsinfo_start = 0; /* no FSINFO structure */
338
 
    fs->free_clusters = -1; /* unknown */
 
332
    fs->data_start = fs->root_start + ROUND_TO_MULTIPLE(fs->root_entries <<
 
333
                                                        MSDOS_DIR_BITS,
 
334
                                                        logical_sector_size);
 
335
    data_size = (loff_t) total_sectors *logical_sector_size - fs->data_start;
 
336
    fs->clusters = data_size / fs->cluster_size;
 
337
    fs->root_cluster = 0;       /* indicates standard, pre-FAT32 root dir */
 
338
    fs->fsinfo_start = 0;       /* no FSINFO structure */
 
339
    fs->free_clusters = -1;     /* unknown */
339
340
    if (!b.fat_length && b.fat32_length) {
340
341
        fs->fat_bits = 32;
341
342
        fs->root_cluster = CF_LE_L(b.root_cluster);
345
346
             * (root_entries != 0), we handle the root dir the old way. Give a
346
347
             * warning, but convertig to a root dir in a cluster chain seems
347
348
             * to complex for now... */
348
 
            printf( "Warning: FAT32 root dir not in cluster chain! "
349
 
                    "Compability mode...\n" );
 
349
            printf("Warning: FAT32 root dir not in cluster chain! "
 
350
                   "Compatibility mode...\n");
350
351
        else if (!fs->root_cluster && !fs->root_entries)
351
352
            die("No root directory!");
352
353
        else if (fs->root_cluster && fs->root_entries)
353
 
            printf( "Warning: FAT32 root dir is in a cluster chain, but "
354
 
                    "a separate root dir\n"
355
 
                    "  area is defined. Cannot fix this easily.\n" );
 
354
            printf("Warning: FAT32 root dir is in a cluster chain, but "
 
355
                   "a separate root dir\n"
 
356
                   "  area is defined. Cannot fix this easily.\n");
356
357
        if (fs->clusters < FAT16_THRESHOLD)
357
 
                printf("Warning: Filesystem is FAT32 according to fat_length "
358
 
                        "and fat32_length fields,\n"
359
 
                        "  but has only %lu clusters, less than the required "
360
 
                        "minimum of %d.\n"
361
 
                        "  This may lead to problems on some systems.\n",
362
 
                        fs->clusters, FAT16_THRESHOLD);
363
 
 
364
 
        fs->backupboot_start = CF_LE_W(b.backup_boot)*logical_sector_size;
365
 
        check_backup_boot(fs,&b,logical_sector_size);
366
 
 
367
 
        read_fsinfo(fs,&b,logical_sector_size);
368
 
    }
369
 
    else if (!atari_format) {
 
358
            printf("Warning: Filesystem is FAT32 according to fat_length "
 
359
                   "and fat32_length fields,\n"
 
360
                   "  but has only %lu clusters, less than the required "
 
361
                   "minimum of %d.\n"
 
362
                   "  This may lead to problems on some systems.\n",
 
363
                   fs->clusters, FAT16_THRESHOLD);
 
364
 
 
365
        fs->backupboot_start = CF_LE_W(b.backup_boot) * logical_sector_size;
 
366
        check_backup_boot(fs, &b, logical_sector_size);
 
367
 
 
368
        read_fsinfo(fs, &b, logical_sector_size);
 
369
    } else if (!atari_format) {
370
370
        /* On real MS-DOS, a 16 bit FAT is used whenever there would be too
371
371
         * much clusers otherwise. */
372
372
        fs->fat_bits = (fs->clusters >= FAT12_THRESHOLD) ? 16 : 12;
373
373
        if (fs->clusters >= FAT16_THRESHOLD)
374
 
                die("Too many clusters (%lu) for FAT16 filesystem.",
375
 
                        fs->clusters);
376
 
    }
377
 
    else {
 
374
            die("Too many clusters (%lu) for FAT16 filesystem.", fs->clusters);
 
375
    } else {
378
376
        /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs
379
377
         * on floppies, and always 16 bit on harddisks. */
380
 
        fs->fat_bits = 16; /* assume 16 bit FAT for now */
 
378
        fs->fat_bits = 16;      /* assume 16 bit FAT for now */
381
379
        /* If more clusters than fat entries in 16-bit fat, we assume
382
380
         * it's a real MSDOS FS with 12-bit fat. */
383
 
        if (fs->clusters+2 > fat_length*logical_sector_size*8/16 ||
 
381
        if (fs->clusters + 2 > fat_length * logical_sector_size * 8 / 16 ||
384
382
            /* if it's a floppy disk --> 12bit fat */
385
383
            device_no == 2 ||
386
384
            /* if it's a ramdisk or loopback device and has one of the usual
392
390
    }
393
391
    /* On FAT32, the high 4 bits of a FAT entry are reserved */
394
392
    fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits;
395
 
    fs->fat_size = fat_length*logical_sector_size;
 
393
    fs->fat_size = fat_length * logical_sector_size;
396
394
 
397
 
    fs->label = calloc(12, sizeof (__u8));
 
395
    fs->label = calloc(12, sizeof(__u8));
398
396
    if (fs->fat_bits == 12 || fs->fat_bits == 16) {
399
 
        struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b;
400
 
        if (b16->extended_sig == 0x29)
401
 
            memmove(fs->label, b16->label, 11);
402
 
        else
403
 
            fs->label = NULL;
 
397
        struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b;
 
398
        if (b16->extended_sig == 0x29)
 
399
            memmove(fs->label, b16->label, 11);
 
400
        else
 
401
            fs->label = NULL;
404
402
    } else if (fs->fat_bits == 32) {
405
 
        if (b.extended_sig == 0x29)
406
 
            memmove(fs->label, &b.label, 11);
407
 
        else
408
 
            fs->label = NULL;
 
403
        if (b.extended_sig == 0x29)
 
404
            memmove(fs->label, &b.label, 11);
 
405
        else
 
406
            fs->label = NULL;
409
407
    }
410
408
 
411
 
    if (fs->clusters > ((unsigned long long)fs->fat_size*8/fs->fat_bits)-2)
 
409
    if (fs->clusters >
 
410
        ((unsigned long long)fs->fat_size * 8 / fs->fat_bits) - 2)
412
411
        die("File system has %d clusters but only space for %d FAT entries.",
413
 
          fs->clusters,((unsigned long long)fs->fat_size*8/fs->fat_bits)-2);
 
412
            fs->clusters,
 
413
            ((unsigned long long)fs->fat_size * 8 / fs->fat_bits) - 2);
414
414
    if (!fs->root_entries && !fs->root_cluster)
415
415
        die("Root directory has zero size.");
416
 
    if (fs->root_entries & (MSDOS_DPS-1))
 
416
    if (fs->root_entries & (MSDOS_DPS - 1))
417
417
        die("Root directory (%d entries) doesn't span an integral number of "
418
 
          "sectors.",fs->root_entries);
419
 
    if (logical_sector_size & (SECTOR_SIZE-1))
 
418
            "sectors.", fs->root_entries);
 
419
    if (logical_sector_size & (SECTOR_SIZE - 1))
420
420
        die("Logical sector size (%d bytes) is not a multiple of the physical "
421
 
          "sector size.",logical_sector_size);
422
 
#if 0 /* linux kernel doesn't check that either */
 
421
            "sector size.", logical_sector_size);
 
422
#if 0                           /* linux kernel doesn't check that either */
423
423
    /* ++roman: On Atari, these two fields are often left uninitialized */
424
424
    if (!atari_format && (!b.secs_track || !b.heads))
425
425
        die("Invalid disk format in boot sector.");
426
426
#endif
427
 
    if (verbose) dump_boot(fs,&b,logical_sector_size);
 
427
    if (verbose)
 
428
        dump_boot(fs, &b, logical_sector_size);
428
429
}
429
430
 
430
 
static void write_boot_label(DOS_FS *fs, char *label)
 
431
static void write_boot_label(DOS_FS * fs, char *label)
431
432
{
432
433
    struct boot_sector b;
433
434
    struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b;
434
435
 
435
436
    fs_read(0, sizeof(b), &b);
436
437
    if (fs->fat_bits == 12 || fs->fat_bits == 16) {
437
 
        if (b16->extended_sig != 0x29) {
438
 
            b16->extended_sig = 0x29;
439
 
            b16->serial = 0;
440
 
            memmove(b16->fs_type, fs->fat_bits == 12 ?"FAT12   ":"FAT16   ", 8);
441
 
        }
442
 
        memmove(b16->label, label, 11);
 
438
        if (b16->extended_sig != 0x29) {
 
439
            b16->extended_sig = 0x29;
 
440
            b16->serial = 0;
 
441
            memmove(b16->fs_type, fs->fat_bits == 12 ? "FAT12   " : "FAT16   ",
 
442
                    8);
 
443
        }
 
444
        memmove(b16->label, label, 11);
443
445
    } else if (fs->fat_bits == 32) {
444
 
        if (b.extended_sig != 0x29) {
445
 
            b.extended_sig = 0x29;
446
 
            b.serial = 0;
447
 
            memmove(b.fs_type, "FAT32   ", 8);
448
 
        }
449
 
        memmove(b.label, label, 11);
 
446
        if (b.extended_sig != 0x29) {
 
447
            b.extended_sig = 0x29;
 
448
            b.serial = 0;
 
449
            memmove(b.fs_type, "FAT32   ", 8);
 
450
        }
 
451
        memmove(b.label, label, 11);
450
452
    }
451
453
    fs_write(0, sizeof(b), &b);
452
454
    if (fs->fat_bits == 32 && fs->backupboot_start)
453
 
        fs_write(fs->backupboot_start, sizeof(b), &b);
 
455
        fs_write(fs->backupboot_start, sizeof(b), &b);
454
456
}
455
457
 
456
 
static loff_t find_volume_de(DOS_FS *fs, DIR_ENT *de)
 
458
static loff_t find_volume_de(DOS_FS * fs, DIR_ENT * de)
457
459
{
458
460
    unsigned long cluster;
459
461
    loff_t offset;
483
485
    return 0;
484
486
}
485
487
 
486
 
static void write_volume_label(DOS_FS *fs, char *label)
 
488
static void write_volume_label(DOS_FS * fs, char *label)
487
489
{
488
490
    time_t now = time(NULL);
489
491
    struct tm *mtime = localtime(&now);
499
501
                                       (mtime->tm_min << 5) +
500
502
                                       (mtime->tm_hour << 11)));
501
503
    de.date = CT_LE_W((unsigned short)(mtime->tm_mday +
502
 
                                       ((mtime->tm_mon+1) << 5) +
503
 
                                       ((mtime->tm_year-80) << 9)));
 
504
                                       ((mtime->tm_mon + 1) << 5) +
 
505
                                       ((mtime->tm_year - 80) << 9)));
504
506
    fs_write(offset, sizeof(DIR_ENT), &de);
505
507
}
506
508
 
507
 
void write_label(DOS_FS *fs, char *label)
 
509
void write_label(DOS_FS * fs, char *label)
508
510
{
509
511
    int l = strlen(label);
510
512
 
511
513
    while (l < 11)
512
 
        label[l++] = ' ';
 
514
        label[l++] = ' ';
513
515
 
514
516
    write_boot_label(fs, label);
515
517
    write_volume_label(fs, label);