|
Lines 39-63
Link Here
|
| 39 |
#include "ext.h" |
39 |
#include "ext.h" |
| 40 |
#include "fsutil.h" |
40 |
#include "fsutil.h" |
| 41 |
|
41 |
|
|
|
42 |
#define IOSIZE 65536 |
| 43 |
|
| 42 |
int |
44 |
int |
| 43 |
readboot(int dosfs, struct bootblock *boot) |
45 |
readboot(int dosfs, struct bootblock *boot) |
| 44 |
{ |
46 |
{ |
|
|
47 |
u_char ioblock[IOSIZE]; |
| 48 |
u_char iofsinfo[IOSIZE]; |
| 49 |
u_char iobackup[IOSIZE]; |
| 45 |
u_char block[DOSBOOTBLOCKSIZE]; |
50 |
u_char block[DOSBOOTBLOCKSIZE]; |
| 46 |
u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; |
51 |
u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; |
| 47 |
u_char backup[DOSBOOTBLOCKSIZE]; |
52 |
u_char backup[DOSBOOTBLOCKSIZE]; |
|
|
53 |
u_char *infop; |
| 54 |
size_t iosize; |
| 55 |
u_int secsize; |
| 48 |
int ret = FSOK; |
56 |
int ret = FSOK; |
| 49 |
int i; |
57 |
int i; |
| 50 |
|
58 |
|
| 51 |
if ((size_t)read(dosfs, block, sizeof block) != sizeof block) { |
59 |
/* Search for an i/o size that works. */ |
|
|
60 |
for (iosize = IOSIZE; iosize >= DOSBOOTBLOCKSIZE; iosize >>= 1) { |
| 61 |
if (lseek(dosfs, (off_t)0, SEEK_SET) == 0 && |
| 62 |
read(dosfs, ioblock, iosize) == (ssize_t)iosize) |
| 63 |
break; |
| 64 |
} |
| 65 |
if (iosize < DOSBOOTBLOCKSIZE) { |
| 52 |
perr("could not read boot block"); |
66 |
perr("could not read boot block"); |
| 53 |
return FSFATAL; |
67 |
return FSFATAL; |
| 54 |
} |
68 |
} |
|
|
69 |
memcpy(block, ioblock, sizeof block); |
| 55 |
|
70 |
|
| 56 |
if (block[510] != 0x55 || block[511] != 0xaa) { |
71 |
/* |
| 57 |
pfatal("Invalid signature in boot block: %02x%02x", |
72 |
* Preliminary decode to determine where the signature might be. |
| 58 |
block[511], block[510]); |
73 |
* It is supposed to be at the end of a 512-block, but we used to |
|
|
74 |
* put it at the end of a sector. Accept the latter so as to fix |
| 75 |
* it someday. |
| 76 |
*/ |
| 77 |
secsize = block[11] + (block[12] << 8); |
| 78 |
if (secsize < sizeof block || secsize > IOSIZE) { |
| 79 |
perror("Preposterous or unsupported sector size"); |
| 59 |
return FSFATAL; |
80 |
return FSFATAL; |
| 60 |
} |
81 |
} |
|
|
82 |
if (block[510] != 0x55 || block[511] != 0xaa) { |
| 83 |
if (ioblock[secsize - 2] != 0x55 || |
| 84 |
ioblock[secsize - 1] != 0xaa) { |
| 85 |
pfatal("Invalid signature in boot block: %02x%02x", |
| 86 |
block[511], block[510]); |
| 87 |
return FSFATAL; |
| 88 |
} |
| 89 |
pwarn( |
| 90 |
"Invalid primary signature in boot block -- using secondary\n"); |
| 91 |
} |
| 61 |
|
92 |
|
| 62 |
memset(boot, 0, sizeof *boot); |
93 |
memset(boot, 0, sizeof *boot); |
| 63 |
boot->ValidFat = -1; |
94 |
boot->ValidFat = -1; |
|
Lines 100-111
Link Here
|
| 100 |
boot->bpbFSInfo = block[48] + (block[49] << 8); |
131 |
boot->bpbFSInfo = block[48] + (block[49] << 8); |
| 101 |
boot->bpbBackup = block[50] + (block[51] << 8); |
132 |
boot->bpbBackup = block[50] + (block[51] << 8); |
| 102 |
|
133 |
|
|
|
134 |
iosize = (secsize >= sizeof fsinfo) ? secsize : sizeof fsinfo; |
| 103 |
if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, |
135 |
if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, |
| 104 |
SEEK_SET) != boot->bpbFSInfo * boot->bpbBytesPerSec |
136 |
SEEK_SET) != boot->bpbFSInfo * boot->bpbBytesPerSec |
| 105 |
|| read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) { |
137 |
|| read(dosfs, iofsinfo, iosize) != (ssize_t)iosize) { |
| 106 |
perr("could not read fsinfo block"); |
138 |
perr("could not read fsinfo block"); |
| 107 |
return FSFATAL; |
139 |
return FSFATAL; |
| 108 |
} |
140 |
} |
|
|
141 |
memcpy(fsinfo, iofsinfo, sizeof fsinfo); |
| 109 |
if (memcmp(fsinfo, "RRaA", 4) |
142 |
if (memcmp(fsinfo, "RRaA", 4) |
| 110 |
|| memcmp(fsinfo + 0x1e4, "rrAa", 4) |
143 |
|| memcmp(fsinfo + 0x1e4, "rrAa", 4) |
| 111 |
|| fsinfo[0x1fc] |
144 |
|| fsinfo[0x1fc] |
|
Lines 116-121
Link Here
|
| 116 |
|| fsinfo[0x3fd] |
149 |
|| fsinfo[0x3fd] |
| 117 |
|| fsinfo[0x3fe] != 0x55 |
150 |
|| fsinfo[0x3fe] != 0x55 |
| 118 |
|| fsinfo[0x3ff] != 0xaa) { |
151 |
|| fsinfo[0x3ff] != 0xaa) { |
|
|
152 |
infop = &iofsinfo[secsize - DOSBOOTBLOCKSIZE]; |
| 153 |
if (memcmp(fsinfo, "RRaA", 4) == 0 && |
| 154 |
memcmp(infop + 0x1e4, "rrAa", 4) == 0 && |
| 155 |
infop[0x1fc] == 0 && |
| 156 |
infop[0x1fd] == 0 && |
| 157 |
infop[0x1fe] == 0x55 && |
| 158 |
infop[0x1ff] == 0xaa) { |
| 159 |
pwarn( |
| 160 |
"Invalid signature in fsinfo block -- using secondary\n"); |
| 161 |
/* |
| 162 |
* Silently fix up the actual fsinfo data |
| 163 |
* (just 2 32-bit words) since this data |
| 164 |
* is advisory and the indentation is |
| 165 |
* already too painful to ask about this. |
| 166 |
*/ |
| 167 |
memcpy(fsinfo + 0x1e8, infop + 0x1e8, 8); |
| 168 |
goto over; |
| 169 |
} |
| 119 |
pwarn("Invalid signature in fsinfo block\n"); |
170 |
pwarn("Invalid signature in fsinfo block\n"); |
| 120 |
if (ask(0, "Fix")) { |
171 |
if (ask(0, "Fix")) { |
| 121 |
memcpy(fsinfo, "RRaA", 4); |
172 |
memcpy(fsinfo, "RRaA", 4); |
|
Lines 126-140
Link Here
|
| 126 |
fsinfo[0x3fc] = fsinfo[0x3fd] = 0; |
177 |
fsinfo[0x3fc] = fsinfo[0x3fd] = 0; |
| 127 |
fsinfo[0x3fe] = 0x55; |
178 |
fsinfo[0x3fe] = 0x55; |
| 128 |
fsinfo[0x3ff] = 0xaa; |
179 |
fsinfo[0x3ff] = 0xaa; |
|
|
180 |
memcpy(iofsinfo, fsinfo, sizeof fsinfo); |
| 129 |
if (lseek(dosfs, boot->bpbFSInfo * |
181 |
if (lseek(dosfs, boot->bpbFSInfo * |
| 130 |
boot->bpbBytesPerSec, SEEK_SET) |
182 |
boot->bpbBytesPerSec, SEEK_SET) |
| 131 |
!= boot->bpbFSInfo * boot->bpbBytesPerSec |
183 |
!= boot->bpbFSInfo * boot->bpbBytesPerSec |
| 132 |
|| write(dosfs, fsinfo, sizeof fsinfo) |
184 |
|| write(dosfs, iofsinfo, iosize) |
| 133 |
!= sizeof fsinfo) { |
185 |
!= (ssize_t)iosize) { |
| 134 |
perr("Unable to write bpbFSInfo"); |
186 |
perr("Unable to write bpbFSInfo"); |
| 135 |
return FSFATAL; |
187 |
return FSFATAL; |
| 136 |
} |
188 |
} |
| 137 |
ret = FSBOOTMOD; |
189 |
ret = FSBOOTMOD; |
|
|
190 |
over: ; |
| 138 |
} else |
191 |
} else |
| 139 |
boot->bpbFSInfo = 0; |
192 |
boot->bpbFSInfo = 0; |
| 140 |
} |
193 |
} |
|
Lines 150-159
Link Here
|
| 150 |
if (lseek(dosfs, boot->bpbBackup * boot->bpbBytesPerSec, |
203 |
if (lseek(dosfs, boot->bpbBackup * boot->bpbBytesPerSec, |
| 151 |
SEEK_SET) |
204 |
SEEK_SET) |
| 152 |
!= boot->bpbBackup * boot->bpbBytesPerSec |
205 |
!= boot->bpbBackup * boot->bpbBytesPerSec |
| 153 |
|| read(dosfs, backup, sizeof backup) != sizeof backup) { |
206 |
|| read(dosfs, iobackup, secsize) != (ssize_t)secsize) { |
| 154 |
perr("could not read backup bootblock"); |
207 |
perr("could not read backup bootblock"); |
| 155 |
return FSFATAL; |
208 |
return FSFATAL; |
| 156 |
} |
209 |
} |
|
|
210 |
memcpy(backup, iobackup, sizeof backup); |
| 157 |
backup[65] = block[65]; /* XXX */ |
211 |
backup[65] = block[65]; /* XXX */ |
| 158 |
if (memcmp(block + 11, backup + 11, 79)) { |
212 |
if (memcmp(block + 11, backup + 11, 79)) { |
| 159 |
/* |
213 |
/* |
|
Lines 237-250
Link Here
|
| 237 |
int |
291 |
int |
| 238 |
writefsinfo(int dosfs, struct bootblock *boot) |
292 |
writefsinfo(int dosfs, struct bootblock *boot) |
| 239 |
{ |
293 |
{ |
|
|
294 |
u_char iofsinfo[IOSIZE]; |
| 240 |
u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; |
295 |
u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; |
|
|
296 |
size_t iosize; |
| 297 |
u_int secsize; |
| 241 |
|
298 |
|
|
|
299 |
secsize = boot->bpbBytesPerSec; |
| 300 |
iosize = (secsize >= sizeof fsinfo) ? secsize : sizeof fsinfo; |
| 242 |
if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET) |
301 |
if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET) |
| 243 |
!= boot->bpbFSInfo * boot->bpbBytesPerSec |
302 |
!= boot->bpbFSInfo * boot->bpbBytesPerSec |
| 244 |
|| read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) { |
303 |
|| read(dosfs, iofsinfo, iosize) != (ssize_t)iosize) { |
| 245 |
perr("could not read fsinfo block"); |
304 |
perr("could not read fsinfo block"); |
| 246 |
return FSFATAL; |
305 |
return FSFATAL; |
| 247 |
} |
306 |
} |
|
|
307 |
memcpy(fsinfo, iofsinfo, sizeof fsinfo); |
| 248 |
fsinfo[0x1e8] = (u_char)boot->FSFree; |
308 |
fsinfo[0x1e8] = (u_char)boot->FSFree; |
| 249 |
fsinfo[0x1e9] = (u_char)(boot->FSFree >> 8); |
309 |
fsinfo[0x1e9] = (u_char)(boot->FSFree >> 8); |
| 250 |
fsinfo[0x1ea] = (u_char)(boot->FSFree >> 16); |
310 |
fsinfo[0x1ea] = (u_char)(boot->FSFree >> 16); |
|
Lines 253-262
Link Here
|
| 253 |
fsinfo[0x1ed] = (u_char)(boot->FSNext >> 8); |
313 |
fsinfo[0x1ed] = (u_char)(boot->FSNext >> 8); |
| 254 |
fsinfo[0x1ee] = (u_char)(boot->FSNext >> 16); |
314 |
fsinfo[0x1ee] = (u_char)(boot->FSNext >> 16); |
| 255 |
fsinfo[0x1ef] = (u_char)(boot->FSNext >> 24); |
315 |
fsinfo[0x1ef] = (u_char)(boot->FSNext >> 24); |
|
|
316 |
memcpy(iofsinfo, fsinfo, sizeof fsinfo); |
| 256 |
if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET) |
317 |
if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET) |
| 257 |
!= boot->bpbFSInfo * boot->bpbBytesPerSec |
318 |
!= boot->bpbFSInfo * boot->bpbBytesPerSec |
| 258 |
|| write(dosfs, fsinfo, sizeof fsinfo) |
319 |
|| write(dosfs, iofsinfo, iosize) != (ssize_t)iosize) { |
| 259 |
!= sizeof fsinfo) { |
|
|
| 260 |
perr("Unable to write bpbFSInfo"); |
320 |
perr("Unable to write bpbFSInfo"); |
| 261 |
return FSFATAL; |
321 |
return FSFATAL; |
| 262 |
} |
322 |
} |