udftools

- Main Page
- Classes
- Files

- File List
- File Members

All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
wrudf-cdr.c
Go to the documentation of this file.
1 /* wrudf-cdr.c
2 *
3 */
4
5 #include "config.h"
6
7 #include <stddef.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include "wrudf.h"
12 #include "ide-pc.h"
13 #include "bswap.h"
14
15 unsigned char *blockBuffer;
16 uint32_t newVATindex;
17 uint32_t sizeVAT;
18 uint32_t prevVATlbn;
19 uint64_t CDRuniqueID; // from VAT FE
20
21
22 uint32_t newVATentry() {
23
24 if( newVATindex + 10 > (sizeVAT >> 2) ) { // ensure enough spave for regid and prevVATlbn
25 sizeVAT += 2048;
26 vat = realloc(vat, sizeVAT);
27 if( vat == NULL )
28 printf("VAT reallocation failed\n");
29 }
30 /* could go through VAT and try to find unused 0xFFFFFFFF entry rather than alloc new one at the end */
31 vat[newVATindex] = getNWA() - pd->partitionStartingLocation;
32 return newVATindex++;
33 }
34
35 uint32_t getNWA() {
36 if( devicetype == DISK_IMAGE )
37 return lseek(device, 0, SEEK_END) >> 11;
38
39 if( read_trackinfo(device, &ti, lastTrack) )
40 printf("Get Track Info failed\n");
41
42 if( ti.nwa_v )
43 return ti.nwa;
44 else
45 return INVALID;
46 }
47
48 uint32_t getMaxVarPktSize() {
49 struct cdrom_buffercapacity bc;
50
51 if( devicetype == DISK_IMAGE )
52 return 1024 * 2048; // nonsense value; just for testing
53
54 read_buffercapacity(device, &bc);
55
56 return ((bc.freeBufferLength >> 11) - 20) << 11; // - 20 :: keep some spare blocks ???
57 }
58
59 unsigned char* readCDR(uint32_t lbn, uint16_t partition) {
60 int stat;
61 uint32_t pbn = getPhysical(lbn, partition);
62
63
64 if( devicetype == DISK_IMAGE ) {
65 stat = lseek(device, 2048 * pbn, SEEK_SET);
66 stat = read(device, blockBuffer, 2048);
67 if( stat != 2048 )
68 fail("readCDR(hd) failed %m\n");
69 else
70 return blockBuffer;
71 }
72
73 stat = readCD(device, sectortype, pbn, 1, blockBuffer);
74
75 if( stat ) {
76 if( ! ignoreReadError )
77 printf("readCDR: %s\n", get_sense_string());
78 return NULL;
79 }
80 return blockBuffer;
81 }
82
83 void
84 writeHD(uint32_t physical, unsigned char* src)
85 {
86 int stat;
87
88 stat = lseek(device, 2048 * physical, SEEK_SET);
89 stat = write(device, src, 2048);
90
91 if( stat != 2048 ) {
92 printf("writeHD failed %m\n");
93 }
94 }
95
96 void syncCDR() {
97 // uint32_t nwa;
98
99 if( device == DISK_IMAGE )
100 return;
101
102 synchronize_cache(device);
103 // nwa = getNWA();
104 // printf("Link from %d to %d\n", nwa-7, nwa-1);
105 }
106
107 void writeHDlink() {
108 uint32_t blk = getNWA();
109 int i;
110
111 for(i = 0; i < 7; i++ )
112 writeHD(blk+i, blockBuffer);
113 }
114
115
116
117 /* writeBlockCDR()
118 * Writes one 2048 byte block
119 */
120 uint32_t
121 writeCDR(void* src) {
122 uint32_t physical;
123
124 physical = getNWA();
125 // printf("Write CDR sector %d\n", physical);
126
127 if( devicetype == DISK_IMAGE )
128 writeHD(physical, src);
129 else {
130 writeCD(device, physical, 1, src);
131 }
132 return physical;
133 }
134
135
136 /* flagError
137 * split up extent in (1) good, (2) bad and (3) good subextents.
138 * In bad extent (2) set logicalBlockNum to zero
139 * If (1) is empty, maybe (2) can be merged with immediately preceding bad extent
140 */
141 long_ad *
142 flagError(long_ad *extents, long_ad *ext, uint32_t pbn)
143 {
144 uint32_t lbn = pbn - pd->partitionStartingLocation;
145 int posInExtent = lbn - ext->extLocation.logicalBlockNum + 1;
146 int blksInExtent = (ext->extLength + 2047) >> 11;
147
148 /* if there is a preceding extent which is bad and
149 * the current bad block is the first in this extent,
150 * then add this bad to the preceding extent
151 */
152 if( ext > extents && lbn == ext->extLocation.logicalBlockNum && !ext[-1].extLocation.logicalBlockNum ) {
153 if( ext[0].extLength < 2048 ) {
154 ext[-1].extLength += ext[0].extLength;
155 ext[0].extLength = 0;
156 } else {
157 ext[-1].extLength += 2048;
158 ext[0].extLength -= 2048;
159 ext[0].extLocation.logicalBlockNum++;
160 }
161 return ext - 1;
162 }
163
164 /* watch one block extents */
165 if( blksInExtent == 1 ) {
166 ext[0].extLocation.logicalBlockNum = 0;
167 return ext;
168 }
169
170 /* 1st block of extent is bad */
171 if( posInExtent == 1 ) {
172 memmove(ext+1, ext, extents - ext + 62);
173 ext[0].extLength = 2048;
174 ext[0].extLocation.logicalBlockNum = 0;
175 ext[1].extLength -= 2048;
176 ext[1].extLocation.logicalBlockNum = lbn + 1;
177 return ext;
178 }
179
180 /* last block of extent is bad - watch partial block */
181 if( posInExtent == blksInExtent ) {
182 memmove(ext+1, ext, extents - ext + 62);
183 ext[1].extLength = ext->extLength - 2048;
184 ext[1].extLocation.logicalBlockNum = 0;
185 ext[0].extLength -= ext[1].extLength;
186 return ext;
187 }
188
189 /* middle block in extent is bad */
190 memmove(ext+2, ext, extents - ext + 61);
191 memcpy(ext+1, ext, sizeof(long_ad));
192 ext[0].extLength = 2048 * posInExtent;
193 ext[1].extLength = 2048;
194 ext[1].extLocation.logicalBlockNum = 0;
195 ext[2].extLength -= ext[0].extLength + 2048;
196 ext[2].extLocation.logicalBlockNum = lbn + 1;
197 return ext+1;
198 }
199
200 int verifyCDR(struct fileEntry *fe) {
201 long_ad *ext, *extents;
202 uint32_t processed;
203 int stat, rv = 0;
204 uint32_t pbn, pbnFE, rewriteBlkno;
205
206 setStrictRead(1);
207 extents = ext = (long_ad*)(fe->allocDescs + fe->lengthExtendedAttr);
208 processed = 0;
209 pbnFE = vat[fe->descTag.tagLocation] + pd->partitionStartingLocation;
210 pbn = ext->extLocation.logicalBlockNum + pd->partitionStartingLocation;
211
212 if( (fe->icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB )
213 goto FileEntryOnly;
214
215 do {
216 if( pbn > pbnFE ) {
217 if( devicetype == DISK_IMAGE ) {
218 printf("Verify %d\n", pbn);
219 stat = 0;
220 // if( (pbn == 557) || pbn == 565 ) stat = 1; /* for testing only */
221 } else
222 stat = readCD(device, sectortype, pbn, 1, blockBuffer);
223
224 if( stat ) {
225 printf("readError %d : %s\n", pbn, get_sense_string());
226 rv++;
227 ext = flagError(extents, ext, pbn);
228 processed = ext->extLength - 2048;
229 }
230 }
231 processed += 2048;
232 pbn++;
233
234 if( processed == ext->extLength ) {
235 ext++;
236 pbn = ext->extLocation.logicalBlockNum + pd->partitionStartingLocation;
237 processed = 0;
238 }
239 } while (processed < ext->extLength);
240
241 FileEntryOnly:
242 if( rv == 0 ) { /* no errors in data, now verify FileEntry */
243 int retries;
244
245 for( retries = 0; retries < 3; retries++ ) {
246 if( devicetype == DISK_IMAGE ) {
247 printf("Verify %d\n", pbnFE);
248 stat = 0;
249 // if( pbnFE == 552 || pbnFE == 553 ) stat = 1; /* testing only */
250 } else
251 stat = readCD(device, sectortype, pbnFE, 1, blockBuffer);
252
253 if( stat == 0 ) {
254 setStrictRead(0);
255 return 0;
256 }
257 printf("readError %d : %s\n", pbnFE, get_sense_string());
258 pbnFE = getNWA();
259 vat[fe->descTag.tagLocation] = pbnFE - pd->partitionStartingLocation;
260 writeCDR(fe);
261 }
262 printf("verifyCDR: verify FE failed 3 times\n");
263 }
264
265 setStrictRead(0);
266
267 rewriteBlkno = getNWA() + 1 - pd->partitionStartingLocation; // NWA itself for revised FileEntry
268
269 fe->lengthAllocDescs = 0;
270 for( ext = extents; ext->extLength; ext++ ) {
271 fe->lengthAllocDescs += sizeof(long_ad);
272 if( ext->extLocation.logicalBlockNum != 0 )
273 continue;
274 ext->extLocation.logicalBlockNum = rewriteBlkno;
275 rewriteBlkno += ext->extLength >> 11;
276 if( ext->extLength & 2047 )
277 break;
278 }
279 fe->descTag.descCRCLength = sizeof(struct fileEntry) + fe->lengthExtendedAttr + fe->lengthAllocDescs - 16;
280 return rv;
281 }
282
283 void readVATtable() {
284 uint32_t blkno;
285 struct fileEntry *fe;
286
287 blkno = getNWA() - (devicetype == DISK_IMAGE ? 1 : 8);
288 prevVATlbn = blkno;
289 fe = (struct fileEntry*)readTaggedBlock(blkno, ABSOLUTE);
290
291 if( fe->descTag.tagIdent != TAG_IDENT_FE || fe->icbTag.fileType != 0 )
292 fail("VAT ICB not found\n");
293
294 CDRuniqueID = fe->uniqueID;
295 sizeVAT = ((fe->informationLength + 4095) & ~2047);
296 vat = malloc(sizeVAT);
297 memset(vat, 0xFF, sizeVAT); // later or not at all
298 newVATindex = (fe->informationLength - 36) >> 2;
299
300 if( sizeof(*fe) + fe->lengthExtendedAttr + fe->informationLength <= 2048 ) {
301 memcpy(vat, fe->allocDescs + fe->lengthExtendedAttr, fe->informationLength - 36);
302 } else {
303 readExtents((char*)vat, 1, fe->allocDescs + fe->lengthExtendedAttr);
304 }
305 }
306
307
308 void
309 writeVATtable()
310 {
311 regid *id;
312 struct fileEntry *fe;
313 uint64_t i;
314 int stat, retries, size;
315 uint32_t startBlk;
316 short_ad *ext;
317
318 retries = 0;
319
320 id = (regid*)(&vat[newVATindex]);
321 memset(id, 0, sizeof(regid));
322 strcpy((char *)id->ident, UDF_ID_ALLOC);
323 *(uint16_t*)id->identSuffix = 0x150;
324 id->identSuffix[2] = UDF_OS_CLASS_UNIX;
325 id->identSuffix[3] = UDF_OS_ID_LINUX;
326 *(uint32_t*)(id+1) = prevVATlbn;
327
328 fe = makeFileEntry();
329 size = (newVATindex + 9) << 2;
330 fe->informationLength = cpu_to_le64(size);
331 fe->descTag.tagSerialNum = lvid->descTag.tagSerialNum;
332 fe->icbTag.fileType = ICBTAG_FILE_TYPE_UNDEF;
333 fe->fileLinkCount = 0;
334
335 for( retries = 0; retries < 8; retries++ ) {
336 startBlk = getNWA();
337
338 if( sizeof(*fe) + size < 2048 ) {
339 fe->icbTag.flags = ICBTAG_FLAG_AD_IN_ICB;
340 memcpy(fe->allocDescs, vat, size);
341 fe->lengthAllocDescs = cpu_to_le32(size);
342 } else {
343 fe->logicalBlocksRecorded = (size + 2047) >> 11;
344 fe->icbTag.flags = ICBTAG_FLAG_AD_SHORT;
345 ext = (short_ad*)(fe->allocDescs + fe->lengthExtendedAttr);
346 ext->extLength = size;
347 ext->extPosition = startBlk - pd->partitionStartingLocation;
348 fe->lengthAllocDescs = cpu_to_le32(16);
349 }
350
351 fe->descTag.tagLocation = startBlk - pd->partitionStartingLocation + fe->logicalBlocksRecorded;
352 fe->descTag.descCRCLength = sizeof(*fe) + fe->lengthExtendedAttr + fe->lengthAllocDescs - sizeof(tag);
353 setChecksum(&fe->descTag);
354
355 for( i = 0; i < fe->logicalBlocksRecorded; i++ )
356 writeCDR(vat + (i<<9));
357
358 writeCDR(fe);
359
360 setStrictRead(1);
361
362 for( i = 0; i <= fe->logicalBlocksRecorded; i++ ) { // "<=" so including FileEntry
363 if( devicetype == DISK_IMAGE ) {
364 printf("Verify %llu\n", (unsigned long long int)(startBlk+i));
365 stat = 0;
366 } else
367 stat = readCD(device, sectortype, startBlk + i, 1, blockBuffer);
368
369 if( stat != 0 ) {
370 printf("writeVATtable verifyError %llu : %s\n", (unsigned long long int)(startBlk + i), get_sense_string());
371 break;
372 }
373 }
374 if( stat == 0 )
375 break;
376 }
377
378 if( retries == 8 )
379 printf("*** writeVATtable rewrite FAILED\nLast VAT was at LBN %d\n", prevVATlbn);
380
381 setStrictRead(0);
382 }
383
384
385
device
int device
Definition: wrudf.c:18
setChecksum
void setChecksum(void *descriptor)
Definition: wrudf-cdrw.c:229
UDF_ID_ALLOC
#define UDF_ID_ALLOC
Definition: osta_udf.h:65
fileEntry::lengthExtendedAttr
uint32_t lengthExtendedAttr
Definition: ecma_167.h:578
INVALID
#define INVALID
Definition: wrudf.h:152
read_buffercapacity
int read_buffercapacity(int fd, struct cdrom_buffercapacity *bufcap)
Definition: ide-pc.c:231
cpu_to_le32
#define cpu_to_le32(x)
Definition: bswap.h:247
synchronize_cache
int synchronize_cache(int fd)
Definition: ide-pc.c:143
getMaxVarPktSize
uint32_t getMaxVarPktSize()
Definition: wrudf-cdr.c:48
readTaggedBlock
void * readTaggedBlock(uint32_t lbn, uint16_t partition)
Definition: wrudf-cdrw.c:639
fileEntry::icbTag
icbtag icbTag
Definition: ecma_167.h:561
cdrom_buffercapacity::freeBufferLength
u_int freeBufferLength
Definition: ide-pc.h:122
blockBuffer
unsigned char * blockBuffer
Definition: wrudf-cdr.c:15
fileEntry::logicalBlocksRecorded
uint64_t logicalBlocksRecorded
Definition: ecma_167.h:570
sectortype
int sectortype
Definition: wrudf-cdrw.c:63
writeHD
void writeHD(uint32_t physical, unsigned char *src)
Definition: wrudf-cdr.c:84
cdrom_trackinfo::nwa
u_int nwa
Definition: ide-pc.h:112
ignoreReadError
int ignoreReadError
Definition: wrudf.c:21
partitionDesc::partitionStartingLocation
uint32_t partitionStartingLocation
Definition: ecma_167.h:269
ICBTAG_FLAG_AD_MASK
#define ICBTAG_FLAG_AD_MASK
Definition: ecma_167.h:525
writeVATtable
void writeVATtable()
Definition: wrudf-cdr.c:309
get_sense_string
char * get_sense_string()
Definition: ide-pc.c:58
ide-pc.h
UDF_OS_ID_LINUX
#define UDF_OS_ID_LINUX
Definition: osta_udf.h:267
verifyCDR
int verifyCDR(struct fileEntry *fe)
Definition: wrudf-cdr.c:200
writeHDlink
void writeHDlink()
Definition: wrudf-cdr.c:107
syncCDR
void syncCDR()
Definition: wrudf-cdr.c:96
fileEntry::fileLinkCount
uint16_t fileLinkCount
Definition: ecma_167.h:565
TAG_IDENT_FE
#define TAG_IDENT_FE
Definition: ecma_167.h:417
flagError
long_ad * flagError(long_ad *extents, long_ad *ext, uint32_t pbn)
Definition: wrudf-cdr.c:142
readCDR
unsigned char * readCDR(uint32_t lbn, uint16_t partition)
Definition: wrudf-cdr.c:59
ICBTAG_FLAG_AD_SHORT
#define ICBTAG_FLAG_AD_SHORT
Definition: ecma_167.h:526
lvid
struct logicalVolIntegrityDesc * lvid
Definition: wrudf.c:71
getPhysical
uint32_t getPhysical(uint32_t lbn, uint16_t part)
Definition: wrudf-cdrw.c:290
readExtents
int readExtents(char *dest, int usesShort, void *extents)
Definition: wrudf-cdrw.c:684
devicetype
int devicetype
Definition: wrudf.c:19
UDF_OS_CLASS_UNIX
#define UDF_OS_CLASS_UNIX
Definition: osta_udf.h:251
writeCD
int writeCD(int fd, int lba, int nblks, unsigned char *buf)
Definition: ide-pc.c:349
ABSOLUTE
#define ABSOLUTE
Definition: wrudf.h:146
fail
void fail(char *fmt,...)
Definition: ide-pc.c:43
fileEntry
Definition: ecma_167.h:558
makeFileEntry
struct fileEntry * makeFileEntry()
Definition: wrudf-desc.c:158
read_trackinfo
int read_trackinfo(int fd, struct cdrom_trackinfo *ti, int trackno)
Definition: ide-pc.c:308
rv
static int rv
Definition: ide-pc.c:39
fileEntry::informationLength
uint64_t informationLength
Definition: ecma_167.h:569
logicalVolIntegrityDesc::descTag
tag descTag
Definition: ecma_167.h:362
lastTrack
int lastTrack
Definition: wrudf-cdrw.c:49
fileEntry::lengthAllocDescs
uint32_t lengthAllocDescs
Definition: ecma_167.h:579
setStrictRead
void setStrictRead(int yes)
Definition: wrudf-cdrw.c:270
fileEntry::descTag
tag descTag
Definition: ecma_167.h:560
CDRuniqueID
uint64_t CDRuniqueID
Definition: wrudf-cdr.c:19
bswap.h
fileEntry::uniqueID
uint64_t uniqueID
Definition: ecma_167.h:577
readCD
int readCD(int fd, int sectortype, int lba, int n, unsigned char *buf)
Definition: ide-pc.c:332
cdrom_trackinfo::nwa_v
u_char nwa_v
Definition: ide-pc.h:109
prevVATlbn
uint32_t prevVATlbn
Definition: wrudf-cdr.c:18
ICBTAG_FLAG_AD_IN_ICB
#define ICBTAG_FLAG_AD_IN_ICB
Definition: ecma_167.h:529
cdrom_buffercapacity
Definition: ide-pc.h:118
vat
uint32_t * vat
Definition: wrudf.c:64
DISK_IMAGE
#define DISK_IMAGE
Definition: wrudf.h:38
wrudf.h
cpu_to_le64
#define cpu_to_le64(x)
Definition: bswap.h:248
newVATindex
uint32_t newVATindex
Definition: wrudf-cdr.c:16
ICBTAG_FILE_TYPE_UNDEF
#define ICBTAG_FILE_TYPE_UNDEF
Definition: ecma_167.h:509
readVATtable
void readVATtable()
Definition: wrudf-cdr.c:283
pd
struct partitionDesc * pd
Definition: wrudf.c:62
getNWA
uint32_t getNWA()
Definition: wrudf-cdr.c:35
fileEntry::allocDescs
uint8_t allocDescs[0]
Definition: ecma_167.h:581
newVATentry
uint32_t newVATentry()
Definition: wrudf-cdr.c:22
sizeVAT
uint32_t sizeVAT
Definition: wrudf-cdr.c:17
ti
struct cdrom_trackinfo ti
Definition: wrudf-cdrw.c:50
writeCDR
uint32_t writeCDR(void *src)
Definition: wrudf-cdr.c:121