udftools

- Main Page
- Classes
- Files

- File List
- File Members

All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
wrudf-cdrw.c
Go to the documentation of this file.
1 /* wrufd-cdrw.c
2 *
3 * PURPOSE
4 * Lowlevel IO routines.
5 * To minimise reading and writing packets wrudf uses a few 64kb packetbuffers.
6 * Blocks to be read are preferentially taken from those buffers and updates written
7 * to the buffers. Buffers that are in-use will not be discarded.
8 * When a new buffer is required preferentially an unused not-dirty buffer gets overwritten.
9 * If not available, then a unused dirty buffer gets written and is then reused.
10 * If no such buffer can be found the system panics.
11 *
12 * COPYRIGHT
13 * This file is distributed under the terms of the GNU General Public
14 * License (GPL). Copies of the GPL can be obtained from:
15 * ftp://prep.ai.mit.edu/pub/gnu/GPL
16 *
17 * (C) 2001 Enno Fennema <e.fennema@dataweb.nl>
18 *
19 * HISTORY
20 * 16 Aug 01 ef Created.
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <errno.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 #include <sys/ioctl.h>
33 #include <linux/cdrom.h> /* for CDROM_DRIVE_STATUS */
34
35 #include "wrudf.h"
36 #include "ide-pc.h"
37 #include "bswap.h"
38
39
40 #define MAXPKTBUFS 4
41 struct packetbuf {
42 uint32_t inuse;
43 uint32_t dirty;
44 uint32_t bufNum;
45 uint32_t start;
46 unsigned char *pkt;
47 };
48
49 int lastTrack;
50 struct cdrom_trackinfo ti;
51 struct read_error_recovery_params *rerp;
52 u_char *rerp_buffer;
53 struct cdrom_cacheparams *cp;
54 u_char *cp_buffer;
55
56 struct packetbuf pktbuf[MAXPKTBUFS+1]; /* last one special use */
57
58 unsigned char *verifyBuffer; /* for verify only */
59 unsigned char *blockBuffer;
60
61 uint32_t trackStart;
62 uint32_t trackSize;
63 int sectortype; /* from track info for readCD() */
64
65 /* declarations */
66 struct packetbuf* findBuf(uint32_t blkno);
67 int readPacket(struct packetbuf* pb);
68 int writePacket(struct packetbuf* pb);
69
70
71 /* markBlock()
72 * FREE or ALLOC block in spacemap
73 */
74 void markBlock(enum markAction action, uint32_t blkno) {
75 uint8_t *bm;
76 uint8_t mask;
77
78 spaceMapDirty = 1;
79 bm = spaceMap->bitmap + (blkno >> 3);
80 mask = 1 << (blkno & 7);
81
82 if( action == FREE ) {
83 *bm |= mask;
84 lvid->freeSpaceTable[pd->partitionNumber]++;
85 } else {
86 *bm &= ~mask;
87 lvid->freeSpaceTable[pd->partitionNumber]--;
88 }
89 }
90
91 /* GetExtents()
92 * Try to find unallocated blocks for 'requestedLength' bytes in the rewritable partition
93 * Return short_ad's of lbns in the physical partition together satisfying that request
94 * Last extent has length < n * 2048; if exact multiple of 2048 the a final length 0 short_ad
95 *
96 * Return value: lenAllocDescs if extents found, 0 if not.
97 */
98 int getExtents(uint32_t requestedLength, short_ad *extents) {
99 uint32_t blkno, lengthFound = 0;
100 short_ad *ext;
101 uint32_t mask, *bm;
102
103 if( medium == CDR ) {
104 /* check space availability */
105 extents->extLength = requestedLength;
106 extents->extPosition = getNWA() - pd->partitionStartingLocation;
107 if( (requestedLength & 2047) == 0 ) {
108 extents[1].extPosition = 0;
109 extents[1].extLength = 0;
110 return 16;
111 } else
112 return 8;
113 }
114
115 // clear extents
116 ext = extents;
117 ext->extLength = 0;
118 bm = ((uint32_t*)spaceMap->bitmap) - 1;
119 mask = 0;
120 blkno = 0xFFFFFFFF;
121
122 while( lengthFound < requestedLength ) {
123 blkno++;
124 mask <<= 1;
125 if( mask == 0 ) {
126 bm++;
127 mask = 1;
128 // check bm within limits
129 }
130 if( (*bm & mask) == 0 ) { // if allocated
131 if( ext->extLength != 0 ) {
132 ext++;
133 if( ext - extents > 31 ) {
134 printf("GetExtents: Too many extents\n");
135 return 0;
136 }
137 ext->extLength = 0;
138 }
139 continue;
140 }
141 if( ext->extLength == 0 )
142 ext->extPosition = blkno;
143 lengthFound += 2048;
144 ext->extLength += 2048;
145 }
146
147 if( requestedLength != lengthFound ) {
148 ext->extLength = ((ext->extLength & ~2047) | (requestedLength & 2047)) - 2048;
149 } else {
150 ext++;
151 ext->extLength = 0;
152 ext->extPosition = 0;
153 }
154 return (uint8_t*)ext - (uint8_t*)extents + sizeof(short_ad);
155 }
156
157
158 int
159 freeShortExtents(short_ad* extents)
160 {
161 uint32_t blkno, lengthFreed;
162 short_ad* ext;
163
164 for( ext = extents; extents->extLength != 0; ext++ ) {
165 blkno = ext->extPosition;
166 for( lengthFreed = 0 ; lengthFreed < ext->extLength; lengthFreed += 2048 ) {
167 markBlock(FREE, blkno);
168 blkno++;
169 }
170 if( ext->extLength & 2047 || (ext+1)->extLength == 0 )
171 break;
172 }
173 return CMND_OK;
174 }
175
176 int freeLongExtents(long_ad* extents) {
177 uint32_t blkno, lengthFreed;
178 long_ad* ext;
179
180 for( ext = extents; extents->extLength != 0; ext++ ) {
181 if( ext->extLocation.partitionReferenceNum != pd->partitionNumber )
182 fail("freeLongExtents: Not RW partition\n");
183 blkno = ext->extLocation.logicalBlockNum;
184 for( lengthFreed = 0 ; lengthFreed < ext->extLength; lengthFreed += 2048 ) {
185 markBlock(FREE, blkno);
186 blkno++;
187 }
188 if( ext->extLength & 2047 || (ext+1)->extLength == 0 )
189 break;
190 }
191 return CMND_OK;
192 }
193
194 /* getUnallocSpaceExtent()
195 * Only used to get new extent for LVID sequence
196 * (Could use to extend sparing blocks as well)
197 */
198 void getUnallocSpaceExtent(uint32_t requestLength, uint32_t requestAfter, extent_ad *alloc) {
199 uint32_t i, n;
200
201 alloc->extLength = alloc->extLocation = 0;
202 n = (requestLength + 2047) & ~2047;
203
204 for( i = 0; i < usd->numAllocDescs; i++ ) {
205 if( usd->allocDescs[i].extLocation > requestAfter ) {
206 if( usd->allocDescs[i].extLength >= requestLength ) {
207 alloc->extLocation = usd->allocDescs[i].extLocation;
208 alloc->extLength = n;
209 usd->allocDescs[i].extLocation += n >> 11;
210 usd->allocDescs[i].extLength -= n;
211 usdDirty = 1;
212 return;
213 } else {
214 alloc->extLocation = usd->allocDescs[i].extLocation;
215 alloc->extLength = usd->allocDescs[i].extLength;
216 usd->numAllocDescs--;
217 for ( ; i < usd->numAllocDescs; i++ )
218 usd->allocDescs[i] = usd->allocDescs[i+1];
219 usdDirty = 1;
220 return;
221 }
222 }
223 }
224 if( requestAfter > 0 )
225 getUnallocSpaceExtent( requestLength, 0, alloc);
226 }
227
228 void
229 setChecksum(void *descriptor)
230 {
231 uint32_t sum;
232 int i;
233 tag *descTag = (tag*) descriptor;
234
235 descTag->descCRC = udf_crc((uint8_t*)descTag + sizeof(tag), descTag->descCRCLength, 0);
236 descTag->tagChecksum = sum = 0;
237 for( i = 0; i < 16; i++ )
238 sum += *((uint8_t*)descTag + i);
239 descTag->tagChecksum = (uint8_t) sum;
240 }
241
242 void
243 updateTimestamp(time_t t, uint32_t ut)
244 {
245 struct timeval timev;
246 struct tm time;
247 int offset;
248
249 if( t == 0 ) {
250 gettimeofday(&timev, NULL);
251 } else {
252 timev.tv_sec = t;
253 timev.tv_usec = ut;
254 }
255
256 localtime_r( &timev.tv_sec, &time);
257 offset = time.tm_gmtoff / 60;
258 timeStamp.typeAndTimezone = 0x1000 + (offset & 0x0FFF); /* 1/3.7.1 */
259 timeStamp.year = time.tm_year + 1900;
260 timeStamp.month = time.tm_mon + 1;;
261 timeStamp.day = time.tm_mday;
262 timeStamp.hour = time.tm_hour;
263 timeStamp.minute = time.tm_min;
264 timeStamp.second = time.tm_sec;
265 timeStamp.centiseconds = timev.tv_usec / 10000;
266 timeStamp.hundredsOfMicroseconds = (timev.tv_usec / 100) % 100;
267 timeStamp.microseconds = timev.tv_usec % 100 ;
268 }
269
270 void setStrictRead(int yes) {
271
272 if( device == DISK_IMAGE )
273 return;
274
275 synchronize_cache(device);
276
277 if( yes ) {
278 rerp->error_recovery_param = 0x04;
279 rerp->retry_count = 2;
280 cp->rcd = 1;
281 } else {
282 rerp->error_recovery_param = 0x00; // back to default
283 rerp->retry_count = 5;
284 cp->rcd = 0;
285 }
286 mode_select(device, rerp_buffer);
287 mode_select(device, cp_buffer);
288 }
289
290 uint32_t getPhysical(uint32_t lbn, uint16_t part) {
291 if( part == 0xFFFF )
292 return lbn;
293 if( part == virtualPartitionNum )
294 lbn = vat[lbn];
295 return lbn + pd->partitionStartingLocation;
296 }
297
298 int cmpBlk(const void* a, const void* b) { /* compare routine for sparing table lookup */
299 if( *(uint32_t*)a < ((struct sparingEntry*)b)->origLocation )
300 return -1;
301 if( *(uint32_t*)a > ((struct sparingEntry*)b)->origLocation )
302 return 1;
303 return 0;
304 }
305
306 /* If the original packet occurs in the Sparing Table return the mappedLocation
307 * else return the original packet address unchanged.
308 */
309 uint32_t lookupSparingTable(uint32_t original) {
310 struct sparingEntry* se;
311
312 if( !st ) // no sparing table found
313 return original;
314
315 se = bsearch(&original, st->mapEntry, usedSparingEntries, sizeof(struct sparingEntry), cmpBlk);
316
317 if( se )
318 return se->mappedLocation;
319 else
320 return original;
321 }
322
323 /* Make an entry in the Sparing Table for packet 'original' and
324 * return the mappedLocation
325 */
326 uint32_t newSparingTableEntry(uint32_t original) {
327 struct sparingEntry *se, newEntry, swapEntry;
328 uint32_t mapped;
329 unsigned int i;
330
331 if( !st ) {
332 printf("No sparing table provided\n");
333 return INVALID;
334 }
335
336 if( usedSparingEntries == st->reallocationTableLen ) {
337 fail("SparingTable full\n");
338 }
339
340 se = bsearch(&original, &st->mapEntry[0], usedSparingEntries, sizeof(struct sparingEntry), cmpBlk);
341
342 if( se ) { /* sparing a sparing packet */
343 se->origLocation = 0xFFFFFFF0;
344 }
345 newEntry.origLocation = original;
346 newEntry.mappedLocation = mapped = st->mapEntry[usedSparingEntries].mappedLocation;
347
348 for( i = 0; i < usedSparingEntries; i++ ) {
349 if( st->mapEntry[i].origLocation < original )
350 continue;
351 }
352 for( ; i <= usedSparingEntries; i++ ) {
353 swapEntry = st->mapEntry[i];
354 st->mapEntry[i] = newEntry;
355 newEntry = swapEntry;
356 }
357 usedSparingEntries++;
358 st->sequenceNum++;
359 sparingTableDirty = 1;
360
361 #ifdef DEBUG
362 printf("Sparing %d to %d\n", original, mapped);
363 #endif
364 return mapped;
365 }
366
367 /* updateSparingTable()
368 * Only done when quitting.
369 * Do not verify writing as that would change the table again.
370 */
371 void updateSparingTable() {
372 size_t i;
373 int pbn, ret;
374 off_t off;
375 ssize_t len;
376 struct generic_desc *p;
377 struct packetbuf *pb;
378 struct sparablePartitionMap *spm = (struct sparablePartitionMap*)lvd->partitionMaps;
379
380 for( i = 0; i < sizeof(spm->locSparingTable)/sizeof(spm->locSparingTable[0]); i++ ) {
381 pbn = spm->locSparingTable[i];
382 if( pbn == 0 )
383 return;
384
385 p = readBlock(pbn, ABSOLUTE);
386 pb = findBuf(pbn);
387 memcpy(p, st, sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry));
388 p->descTag.tagLocation = pbn;
389 p->descTag.descCRCLength =
390 sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry) - sizeof(tag);
391 setChecksum(p);
392 if( devicetype != DISK_IMAGE ) {
393 ret = writeCD(device, pbn, 32, pb->pkt);
394 if( ret )
395 printf("Write SparingTable at %d: %s\n", pbn, get_sense_string());
396 } else { // DISK_IMAGE
397 off = lseek(device, 2048 * pbn, SEEK_SET);
398 if( off == (off_t)-1 )
399 fail("writeSparingTable at %d: %m\n", pbn);
400 len = write(device, pb->pkt, 32 * 2048);
401 if( len < 0 )
402 fail("writeSparingTable at %d: %m\n", pbn);
403 if( len != 32 * 2048 )
404 fail("writeSparingTable at %d: %s\n", pbn, strerror(EIO));
405 }
406 }
407 }
408
409
410 int
411 readPacket(struct packetbuf* pb)
412 {
413 int ret;
414 off_t off;
415 ssize_t len;
416 uint32_t physical;
417
418 physical = lookupSparingTable(pb->start);
419
420 if( devicetype != DISK_IMAGE ) {
421 ret = readCD(device, sectortype, physical, 32, pb->pkt);
422 if( ret )
423 printf("readPacket: readCD %s\n", get_sense_string());
424 } else {
425 off = lseek(device, 2048 * physical, SEEK_SET);
426 if( off == (off_t)-1 )
427 fail("readPacket: lseek failed %m\n");
428 len = read(device, pb->pkt, 32 * 2048);
429 if( len < 0 )
430 fail("readPacket: read failed %m\n");
431 if( len != 32 * 2048 )
432 fail("readPacket: read failed %s\n", strerror(EIO));
433 ret = 0;
434 }
435 return ret;
436 }
437
438
439 int
440 writePacket(struct packetbuf* pb)
441 {
442 int ret, retry;
443 off_t off;
444 ssize_t len;
445 uint32_t physical;
446
447 pb->dirty = 0;
448 physical = lookupSparingTable(pb->start);
449
450 if( devicetype != DISK_IMAGE ) {
451 for(retry = 0; retry < 2; retry++ ) {
452 if( retry != 0 )
453 physical = newSparingTableEntry(pb->start);
454
455 ret = writeCD(device, physical, 32, pb->pkt);
456
457 if( ret )
458 fail("writePacket: writeCD %s\n", get_sense_string());
459
460 // must now verify write operation and spare if necessary
461 // My HP8100 does not support Verify or WriteAndVerify
462 // Use ReadCD with strict Read Error Recovery Parameters
463 setStrictRead(1);
464 ret = readCD(device, sectortype, physical, 32, verifyBuffer);
465
466 if( ret == 0 ) {
467 setStrictRead(0);
468 return 0;
469 }
470 printf("writePacket: verify %s\n", get_sense_string());
471 }
472 setStrictRead(0);
473 } else { // DISK_IMAGE
474 #ifdef DEBUG_SPARING // force sparing on packets of disk image
475 if( st ) {
476 if( physical == 0x820 || physical == 0x880 ) // arbitrary 'bad' blocks
477 physical = newSparingTableEntry(pb->start);
478 }
479 #endif
480 off = lseek(device, 2048 * physical, SEEK_SET);
481 if( off == (off_t)-1 )
482 fail("writePacket: writeHD failed %m\n");
483 len = write(device, pb->pkt, 32 * 2048);
484 if( len < 0 )
485 fail("writePacket: writeHD failed %m\n");
486 if( len != 32 * 2048 )
487 fail("writePacket: writeHD failed %s\n", strerror(EIO));
488 ret = 0;
489 }
490 return ret;
491 }
492
493
494 struct packetbuf*
495 findBuf(uint32_t blkno)
496 {
497 struct packetbuf *b;
498
499 blkno &= ~31;
500 for(b = &pktbuf[0]; b < &pktbuf[MAXPKTBUFS]; b++ ) {
501 if( blkno == b->start )
502 return b;
503 }
504 return NULL;
505 }
506
507
508 struct packetbuf*
509 getFreePacketBuffer(uint32_t lbn, uint16_t part)
510 {
511 struct packetbuf *b, *bFree, *bMustWrite;
512 uint32_t blkno;
513
514 blkno = lbn + ( part == 0xFFFF ? 0 : pd->partitionStartingLocation );
515 bFree = bMustWrite = NULL;
516
517 for( b = &pktbuf[0]; b < &pktbuf[MAXPKTBUFS]; b++ ) {
518 if( (b->inuse | b->dirty) == 0 ) {
519 bFree = b;
520 break;
521 } else
522 if( b->inuse == 0 )
523 bMustWrite = b;
524 }
525
526 if( !bFree && !bMustWrite ) {
527 printf("readBlock: Permission to panic, Sir!!!\n");
528 return NULL;
529 }
530
531 if( !bFree ) {
532 writePacket(bMustWrite);
533 bMustWrite->inuse = 0;
534 bMustWrite->dirty = 0;
535 bFree = bMustWrite;
536 }
537
538 bFree->start = blkno & ~31;
539 return bFree;
540 }
541
542 void*
543 readBlock(uint32_t lbn, uint16_t part)
544 {
545 struct packetbuf *b;
546 uint32_t physical = getPhysical(lbn, part);
547
548 if( medium == CDR )
549 return readCDR(physical, ABSOLUTE);
550
551 b = findBuf(physical);
552
553 if( !b ) {
554 b = getFreePacketBuffer(lbn, part);
555 readPacket(b);
556 }
557
558 b->inuse |= 0x80000000 >> (lbn & 31);
559 return b->pkt + ((lbn & 31) << 11);
560 }
561
562
563 void*
564 readSingleBlock(uint32_t pbn)
565 {
566 int ret;
567 off_t off;
568 ssize_t len;
569
570 if( devicetype != DISK_IMAGE ) {
571 ret = readCD(device, sectortype, pbn, 1, blockBuffer);
572 if( ret ) {
573 if( ! ignoreReadError )
574 printf("readSingleBlock: %s\n", get_sense_string());
575 return NULL;
576 } else
577 return blockBuffer;
578 } else {
579 off = lseek(device, 2048 * pbn, SEEK_SET);
580 if( off != (off_t)-1 )
581 return NULL;
582 len = read(device, blockBuffer, 2048);
583 if( len != 2048 )
584 return NULL;
585 else
586 return blockBuffer;
587 }
588 }
589
590
591 void
592 freeBlock(uint32_t lbn, uint16_t part)
593 {
594 struct packetbuf *b;
595 uint32_t blkno;
596
597 if( medium == CDR ) return;
598
599 blkno = lbn + ( part == 0xFFFF ? 0 : pd->partitionStartingLocation );
600 b = findBuf(blkno);
601
602 if( !b )
603 fail("freeBlock failed on block %d\n", blkno);
604
605 b->inuse &= ~(0x80000000 >> (blkno & 31)); /* turn off INUSE bit */
606 }
607
608
609 void
610 dirtyBlock(uint32_t lbn, uint16_t part)
611 {
612 struct packetbuf *pb;
613 uint32_t blkno;
614
615 blkno = lbn + ( part == 0xFFFF ? 0 : pd->partitionStartingLocation );
616 pb = findBuf(blkno);
617
618 if( !pb )
619 fail("dirtyBlock failed on block %d\n", blkno);
620
621 pb->dirty |= 0x80000000 >> (blkno & 31); /* turn on DIRTY bit */
622 }
623
624 void
625 writeBlock(uint32_t lbn, uint16_t part, void* src)
626 {
627 char *p;
628
629 p = readBlock(lbn, part);
630 memcpy(p, src, 2048);
631 if( part != ABSOLUTE )
632 markBlock(ALLOC, lbn);
633 dirtyBlock(lbn, part);
634 freeBlock(lbn, part);
635 }
636
637
638 void*
639 readTaggedBlock(uint32_t lbn, uint16_t partition)
640 {
641 int i;
642 uint8_t sum, *p;
643 struct generic_desc *block;
644
645
646 if( medium == CDR )
647 block = (struct generic_desc*) readCDR(lbn, partition);
648 else {
649 block = (struct generic_desc*) readBlock(lbn, partition);
650 freeBlock(lbn,partition);
651
652 if( !block )
653 return block;
654 }
655
656 if( block->descTag.tagIdent == 0x0000 ) {
657 /* ignore not ISO 13346 defined descriptors with 0 tags */
658 if( strncmp((char *)((struct sparingTable*)block)->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING)) != 0 ) {
659 for( i = 0; i < 2048; i++ ) {
660 if( ((uint8_t*)block)[i] != 0 ) {
661 printf("readTaggedBlock: Empty block %d not all zeroes\n", lbn);
662 break;
663 }
664 }
665 return block;
666 }
667 }
668
669 for( i = 0, sum = 0, p = (uint8_t*)block; i< 16; i++ )
670 if( i != 4 )
671 sum += *(p + i);
672
673 if( block->descTag.tagChecksum != sum )
674 fail("readTagged: Checksum error in block %d\n", lbn);
675
676 if( block->descTag.descCRC != udf_crc((uint8_t*)block + sizeof(tag), ((tag*)block)->descCRCLength, 0) )
677 fail("readTagged: CRC error in block %d\n", lbn);
678
679 return block;
680 }
681
682
683 int
684 readExtents(char* dest, int usesShort, void* extents)
685 {
686 uint len, blkno, partitionNumber;
687 char *p;
688 long_ad *lo;
689 short_ad *sh;
690
691 if( usesShort ) {
692 sh = (short_ad*) extents;
693 len = sh->extLength;
694 blkno = sh->extPosition;
695 partitionNumber = pd->partitionNumber;
696 } else {
697 lo = (long_ad*) extents;
698 len = lo->extLength;
699 blkno = lo->extLocation.logicalBlockNum;
700 partitionNumber = lo->extLocation.partitionReferenceNum;
701 }
702
703 for(;;) {
704 p = readBlock(blkno, partitionNumber);
705 memcpy(dest, p, 2048);
706 freeBlock(blkno, partitionNumber);
707 dest += 2048;
708 if( len < 2048 )
709 break;
710 if( len == 0 ) {
711 if( usesShort ) {
712 sh++;
713 len = sh->extLength;
714 blkno = sh->extPosition;
715 } else {
716 lo++;
717 len = lo->extLength;
718 blkno = lo->extLocation.logicalBlockNum;
719 partitionNumber = lo->extLocation.partitionReferenceNum;
720 }
721 if( len == 0 )
722 break;
723 continue;
724 }
725 len -= 2048;
726 blkno++;
727 }
728 return CMND_OK;
729 }
730
731
732 int
733 writeExtents(char* src, int usesShort, void* extents)
734 {
735 uint len, blkno, partitionNumber;
736 long_ad *lo=NULL;
737 short_ad *sh=NULL;
738
739 if( usesShort ) {
740 sh = (short_ad*) extents;
741 len = sh->extLength;
742 blkno = sh->extPosition;
743 partitionNumber = pd->partitionNumber;
744 } else {
745 lo = (long_ad*) extents;
746 len = lo->extLength;
747 blkno = lo->extLocation.logicalBlockNum;
748 partitionNumber = lo->extLocation.partitionReferenceNum;
749 }
750
751 for(;;) {
752 writeBlock(blkno, partitionNumber, src);
753 src += 2048;
754 if( len < 2048)
755 break;
756 if( len == 2048 ) {
757 if( usesShort ) {
758 sh++;
759 len = sh->extLength;
760 blkno = sh->extPosition;
761 } else {
762 lo++;
763 len = lo->extLength;
764 blkno = lo->extLocation.logicalBlockNum;
765 partitionNumber = lo->extLocation.partitionReferenceNum;
766 }
767 if( len == 0 )
768 break;
769 continue;
770 }
771 len -= 2048;
772 blkno++;
773 }
774 return CMND_OK;
775 }
776
777
778 int
779 initIO(char *filename)
780 {
781 struct packetbuf *pb;
782 int rv;
783 off_t off;
784 ssize_t len;
785 struct stat filestat;
786 struct cdrom_discinfo di;
787 u_char *buffer;
788 struct cdrom_writeparams *wp;
789 uint16_t ident;
790
791 if( (rv = stat(filename, &filestat)) < 0 )
792 fail("initIO: stat on %s failed\n", filename);
793
794 if( S_ISREG(filestat.st_mode) ) { /* disk image of a UDF volume */
795 devicetype = DISK_IMAGE;
796 if( (device = open(filename, O_RDWR)) < 0 ) {
797 fail("initIO: open %s failed\n", filename);
798 return 0;
799 }
800
801 /* heuristically determine medium imitated on disk image based on VAT FileEntry in block 512 */
802 off = lseek(device, 2048 * 512, SEEK_SET);
803 if( off == (off_t)-1 )
804 fail("initIO: lseek %s failed: %m\n", filename);
805 len = read(device, &ident, 2);
806 if( len < 0 )
807 fail("initIO: read %s failed: %m\n", filename);
808 if( len != 2 )
809 fail("initIO: read %s failed: %s\n", filename, strerror(EIO));
810 medium = ident == TAG_IDENT_VDP ? CDR : CDRW;
811
812 if( medium == CDRW ) {
813 for( pb = pktbuf, rv = 1; pb <= pktbuf + MAXPKTBUFS; pb++ ) {
814 pb->start = 0xFFFFFFFF;
815 pb->pkt = malloc(32*2048);
816 pb->bufNum = rv++;
817 if( pb->pkt == NULL )
818 fail("malloc packetBuffer failed\n");
819 }
820 }
821 }
822
823 if( (blockBuffer = malloc(2048)) == NULL )
824 fail("malloc blockBuffer failed\n");
825
826 if( devicetype == DISK_IMAGE )
827 return 0;
828
829 if( (device = open(filename, O_RDONLY | O_NONBLOCK )) < 0 )
830 fail("initIO: open %s failed\n", filename);
831
832 rv = ioctl(device, CDROM_DRIVE_STATUS);
833
834 if( (rv != CDS_DISC_OK) && (rv != CDS_NO_INFO) )
835 fail("No disc or not ready\n");
836
837 if( read_discinfo(device, &di) )
838 fail("Read discinfo failed\n");
839
840 if( di.erasable == 0 ) {
841 medium = CDR;
842 printf("CDR disc\n");
843 } else {
844 medium = CDRW;
845 printf("CDRW disc\n");
846 }
847
848 lastTrack = di.trk1_lastsession;
849
850 if( read_trackinfo(device, &ti, lastTrack) ) /* last track 1 in last session writable for UDF */
851 fail("Read discinfo failed\n");
852
853 if( medium == CDRW ) {
854 if( !ti.fixpkt ) {
855 printf("Assume CDRW disc used as CDR\n");
856 medium = CDR;
857 } else if ( ti.fixpkt_size != 32 )
858 fail("CDRW not fixed 32 sector packets\n");
859 }
860
861 if( medium == CDRW ) {
862 for( pb = pktbuf, rv = 1; pb <= pktbuf + MAXPKTBUFS; pb++ ) {
863 pb->start = 0xFFFFFFFF;
864 pb->pkt = malloc(32*2048);
865 pb->bufNum = rv++;
866 if( pb->pkt == NULL )
867 fail("malloc packetBuffer failed\n");
868 }
869 if( (verifyBuffer = malloc(32 * 2048)) == NULL )
870 fail("malloc verifyBuffer failed\n");
871 }
872
873 if( medium == CDR ) {
874 if( ti.rsrvd_trk || ! ti.packet || ti.fixpkt )
875 fail("CDR disc last track reserved or not variable packet\n");
876
877 if( !ti.nwa_v )
878 fail("Next writable address invalid in track %d\n", ti.trk);
879 }
880
881 trackStart = ti.trk_start;
882 trackSize = ti.trk_size;
883
884 if( ti.data_mode == 1 )
885 sectortype = 2; /* for readCD() */
886 else if( ti.data_mode == 2 )
887 sectortype = 4;
888 else
889 fail("Neither Data Mode1 nor Mode2 on disc\n");
890
891 /* get read error recovery parameters page */
892 rv = mode_sense(device, &rerp_buffer, (void *)&rerp, GPMODE_R_W_ERROR_PAGE, PGCTL_CURRENT_VALUES);
893
894 /* get cache parameters page */
895 rv = mode_sense(device, &cp_buffer, (void *)&cp, GPMODE_CACHE_PAGE, PGCTL_CURRENT_VALUES);
896
897 /* setup write params */
898 get_writeparams(device, &buffer, &wp, PGCTL_CURRENT_VALUES);
899
900 wp->write_type = 0;
901 // wp->trk_mode = 7;
902 wp->copy = 0;
903 wp->fp = medium == CDRW ? 1 : 0;
904 wp->test_write = 0;
905 wp->data_blk_type = ( ti.data_mode == 2 ? DB_XA_F1 : DB_ROM_MODE1);
906 wp->host_appl_code = 0;
907 wp->session_format = (ti.data_mode == 2 ? 0x20 : 0x00);
908 wp->pkt_size = medium == CDRW ? 32 : 0;
909 wp->subhdr0 = 0x00;
910 wp->subhdr1 = 0x00;
911 wp->subhdr2 = 0x08;
912 wp->subhdr3 = 0x00;
913
914 if( (rv = set_writeparams(device, buffer, wp)) )
915 {
916 free(buffer);
917 fail("Set write parameters failed\n");
918 }
919 else
920 free(buffer);
921
922 return 0;
923 }
924
925
926 int
927 closeIO(void)
928 {
929 struct packetbuf *pb;
930
931 if( medium == CDRW ) {
932 for( pb = pktbuf; pb < pktbuf + MAXPKTBUFS; pb++ ) {
933 if( pb->dirty && !pb->inuse )
934 writePacket(pb);
935 if( pb->inuse || pb->dirty)
936 printf("PacketBuffet[%d] at %d inuse %08X dirty %08X\n",
937 pb->bufNum, pb->start, pb->inuse, pb->dirty);
938 free(pb->pkt);
939 }
940 }
941
942 if( blockBuffer ) free(blockBuffer);
943 if( verifyBuffer ) free(verifyBuffer);
944
945 if( devicetype != DISK_IMAGE )
946 synchronize_cache(device);
947
948 close(device);
949 return 1;
950 }
timeStamp
timestamp timeStamp
Definition: wrudf.c:49
device
int device
Definition: wrudf.c:18
setChecksum
void setChecksum(void *descriptor)
Definition: wrudf-cdrw.c:229
closeIO
int closeIO(void)
Definition: wrudf-cdrw.c:927
cdrom_trackinfo::trk_size
u_int trk_size
Definition: ide-pc.h:115
cdrom_trackinfo::data_mode
u_char data_mode
Definition: ide-pc.h:104
INVALID
#define INVALID
Definition: wrudf.h:152
set_writeparams
int set_writeparams(int fd, u_char *buffer, struct cdrom_writeparams *wp)
Definition: ide-pc.c:495
get_writeparams
int get_writeparams(int fd, u_char **buffer, struct cdrom_writeparams **wp, int pgctl)
Definition: ide-pc.c:486
sparingEntry
Definition: osta_udf.h:186
cdrom_writeparams::subhdr3
u_char subhdr3
Definition: ide-pc.h:229
cp
struct cdrom_cacheparams * cp
Definition: wrudf-cdrw.c:53
synchronize_cache
int synchronize_cache(int fd)
Definition: ide-pc.c:143
descTag
tag descTag
Definition: ecma_167.h:64
readTaggedBlock
void * readTaggedBlock(uint32_t lbn, uint16_t partition)
Definition: wrudf-cdrw.c:639
cdrom_cacheparams
Definition: ide-pc.h:163
sparingIdent
regid sparingIdent
Definition: osta_udf.h:162
freeLongExtents
int freeLongExtents(long_ad *extents)
Definition: wrudf-cdrw.c:176
sparingTable::mapEntry
struct sparingEntry mapEntry[0]
Definition: osta_udf.h:199
sparingTable
Definition: osta_udf.h:192
readSingleBlock
void * readSingleBlock(uint32_t pbn)
Definition: wrudf-cdrw.c:564
pktbuf
struct packetbuf pktbuf[MAXPKTBUFS+1]
Definition: wrudf-cdrw.c:56
sparablePartitionMap::locSparingTable
uint32_t locSparingTable[4]
Definition: osta_udf.h:153
updateSparingTable
void updateSparingTable()
Definition: wrudf-cdrw.c:371
partitionDesc::partitionNumber
uint16_t partitionNumber
Definition: ecma_167.h:265
read_error_recovery_params::retry_count
u_char retry_count
Definition: ide-pc.h:157
trackStart
uint32_t trackStart
Definition: wrudf-cdrw.c:61
sectortype
int sectortype
Definition: wrudf-cdrw.c:63
ignoreReadError
int ignoreReadError
Definition: wrudf.c:21
read_error_recovery_params::error_recovery_param
u_char error_recovery_param
Definition: ide-pc.h:156
partitionDesc::partitionStartingLocation
uint32_t partitionStartingLocation
Definition: ecma_167.h:269
medium
enum MEDIUM medium
Definition: wrudf.c:20
unallocSpaceDesc::numAllocDescs
uint32_t numAllocDescs
Definition: ecma_167.h:348
markBlock
void markBlock(enum markAction action, uint32_t blkno)
Definition: wrudf-cdrw.c:74
spaceMapDirty
int spaceMapDirty
Definition: wrudf.c:76
udf_crc
uint16_t udf_crc(uint8_t *, uint32_t, uint16_t)
Definition: crc.c:88
sparablePartitionMap
Definition: osta_udf.h:141
origLocation
uint32_t origLocation
Definition: osta_udf.h:161
get_sense_string
char * get_sense_string()
Definition: ide-pc.c:58
cmpBlk
int cmpBlk(const void *a, const void *b)
Definition: wrudf-cdrw.c:298
UDF_ID_SPARING
#define UDF_ID_SPARING
Definition: osta_udf.h:66
cdrom_writeparams::data_blk_type
u_char data_blk_type
Definition: ide-pc.h:197
generic_desc
Definition: wrudf.h:28
writePacket
int writePacket(struct packetbuf *pb)
Definition: wrudf-cdrw.c:440
verifyBuffer
unsigned char * verifyBuffer
Definition: wrudf-cdrw.c:58
cdrom_trackinfo::trk_start
u_int trk_start
Definition: ide-pc.h:111
sparingTable::reallocationTableLen
uint16_t reallocationTableLen
Definition: osta_udf.h:196
ide-pc.h
read_error_recovery_params
Definition: ide-pc.h:151
mode_sense
int mode_sense(int fd, unsigned char *buffer, int page, char pc, int size)
Definition: cdrwtool.c:163
CDRW
Definition: wrudf.h:40
cdrom_writeparams::copy
u_char copy
Definition: ide-pc.h:190
logicalVolIntegrityDesc::freeSpaceTable
uint32_t freeSpaceTable[0]
Definition: ecma_167.h:369
uint
#define uint(x)
Definition: file.c:604
packetbuf::bufNum
uint32_t bufNum
Definition: wrudf-cdrw.c:44
cdrom_writeparams::host_appl_code
u_char host_appl_code
Definition: ide-pc.h:218
virtualPartitionNum
uint16_t virtualPartitionNum
Definition: wrudf.c:63
readBlock
void * readBlock(uint32_t lbn, uint16_t part)
Definition: wrudf-cdrw.c:543
freeBlock
void freeBlock(uint32_t lbn, uint16_t part)
Definition: wrudf-cdrw.c:592
lookupSparingTable
uint32_t lookupSparingTable(uint32_t original)
Definition: wrudf-cdrw.c:309
getUnallocSpaceExtent
void getUnallocSpaceExtent(uint32_t requestLength, uint32_t requestAfter, extent_ad *alloc)
Definition: wrudf-cdrw.c:198
TAG_IDENT_VDP
#define TAG_IDENT_VDP
Definition: ecma_167.h:184
findBuf
struct packetbuf * findBuf(uint32_t blkno)
Definition: wrudf-cdrw.c:495
cdrom_trackinfo::fixpkt_size
u_int fixpkt_size
Definition: ide-pc.h:114
readCDR
unsigned char * readCDR(uint32_t lbn, uint16_t partition)
Definition: wrudf-cdr.c:59
read_discinfo
int read_discinfo(int fd, struct cdrom_discinfo *di)
Definition: ide-pc.c:270
lvid
struct logicalVolIntegrityDesc * lvid
Definition: wrudf.c:71
partitionNumber
uint16_t partitionNumber
Definition: ecma_167.h:67
getPhysical
uint32_t getPhysical(uint32_t lbn, uint16_t part)
Definition: wrudf-cdrw.c:290
PGCTL_CURRENT_VALUES
#define PGCTL_CURRENT_VALUES
Definition: ide-pc.h:136
readExtents
int readExtents(char *dest, int usesShort, void *extents)
Definition: wrudf-cdrw.c:684
unallocSpaceDesc::allocDescs
extent_ad allocDescs[0]
Definition: ecma_167.h:349
packetbuf::inuse
uint32_t inuse
Definition: wrudf-cdrw.c:42
cdrom_cacheparams::rcd
u_char rcd
Definition: ide-pc.h:168
dirtyBlock
void dirtyBlock(uint32_t lbn, uint16_t part)
Definition: wrudf-cdrw.c:610
generic_desc::descTag
tag descTag
Definition: wrudf.h:30
devicetype
int devicetype
Definition: wrudf.c:19
cdrom_trackinfo::trk
u_char trk
Definition: ide-pc.h:97
blockBuffer
unsigned char * blockBuffer
Definition: wrudf-cdrw.c:59
writeCD
int writeCD(int fd, int lba, int nblks, unsigned char *buf)
Definition: ide-pc.c:349
usdDirty
int usdDirty
Definition: wrudf.c:76
CDR
Definition: wrudf.h:40
ABSOLUTE
#define ABSOLUTE
Definition: wrudf.h:146
fail
void fail(char *fmt,...)
Definition: ide-pc.c:43
usd
struct unallocSpaceDesc * usd
Definition: wrudf.c:69
packetbuf::start
uint32_t start
Definition: wrudf-cdrw.c:45
read_trackinfo
int read_trackinfo(int fd, struct cdrom_trackinfo *ti, int trackno)
Definition: ide-pc.c:308
cdrom_writeparams::test_write
u_char test_write
Definition: ide-pc.h:186
rv
static int rv
Definition: ide-pc.c:39
getExtents
int getExtents(uint32_t requestedLength, short_ad *extents)
Definition: wrudf-cdrw.c:98
cdrom_writeparams::subhdr0
u_char subhdr0
Definition: ide-pc.h:226
lastTrack
int lastTrack
Definition: wrudf-cdrw.c:49
sparingTableDirty
int sparingTableDirty
Definition: wrudf.c:76
MAXPKTBUFS
#define MAXPKTBUFS
Definition: wrudf-cdrw.c:40
CMND_OK
Definition: wrudf.h:60
st
struct sparingTable * st
Definition: wrudf.c:74
setStrictRead
void setStrictRead(int yes)
Definition: wrudf-cdrw.c:270
spaceMap
struct spaceBitmapDesc * spaceMap
Definition: wrudf.c:70
sparingEntry::mappedLocation
uint32_t mappedLocation
Definition: osta_udf.h:189
sparingTable::sequenceNum
uint32_t sequenceNum
Definition: osta_udf.h:198
rerp_buffer
u_char * rerp_buffer
Definition: wrudf-cdrw.c:52
cdrom_writeparams::fp
u_char fp
Definition: ide-pc.h:191
cp_buffer
u_char * cp_buffer
Definition: wrudf-cdrw.c:54
cdrom_trackinfo::fixpkt
u_char fixpkt
Definition: ide-pc.h:105
bswap.h
writeBlock
void writeBlock(uint32_t lbn, uint16_t part, void *src)
Definition: wrudf-cdrw.c:625
packetbuf
Definition: wrudf-cdrw.c:41
cdrom_writeparams::subhdr2
u_char subhdr2
Definition: ide-pc.h:228
cdrom_writeparams::subhdr1
u_char subhdr1
Definition: ide-pc.h:227
rerp
struct read_error_recovery_params * rerp
Definition: wrudf-cdrw.c:51
readCD
int readCD(int fd, int sectortype, int lba, int n, unsigned char *buf)
Definition: ide-pc.c:332
logicalVolDesc::partitionMaps
uint8_t partitionMaps[0]
Definition: ecma_167.h:310
cdrom_trackinfo::nwa_v
u_char nwa_v
Definition: ide-pc.h:109
updateTimestamp
void updateTimestamp(time_t t, uint32_t ut)
Definition: wrudf-cdrw.c:243
cdrom_trackinfo::packet
u_char packet
Definition: ide-pc.h:106
initIO
int initIO(char *filename)
Definition: wrudf-cdrw.c:779
vat
uint32_t * vat
Definition: wrudf.c:64
cdrom_discinfo::trk1_lastsession
u_char trk1_lastsession
Definition: ide-pc.h:78
markAction
markAction
Definition: wrudf.h:127
DISK_IMAGE
#define DISK_IMAGE
Definition: wrudf.h:38
wrudf.h
trackSize
uint32_t trackSize
Definition: wrudf-cdrw.c:62
cdrom_writeparams
Definition: ide-pc.h:179
DB_XA_F1
#define DB_XA_F1
Definition: ide-pc.h:208
FREE
Definition: wrudf.h:127
GPMODE_CACHE_PAGE
#define GPMODE_CACHE_PAGE
Definition: ide-pc.h:161
cdrom_discinfo::erasable
u_char erasable
Definition: ide-pc.h:72
spaceBitmapDesc::bitmap
uint8_t bitmap[0]
Definition: ecma_167.h:754
cdrom_writeparams::write_type
u_char write_type
Definition: ide-pc.h:185
lvd
struct logicalVolDesc * lvd
Definition: wrudf.c:68
mode_select
int mode_select(int fd, unsigned char *buffer, int len)
Definition: cdrwtool.c:150
writeExtents
int writeExtents(char *src, int usesShort, void *extents)
Definition: wrudf-cdrw.c:733
freeShortExtents
int freeShortExtents(short_ad *extents)
Definition: wrudf-cdrw.c:159
sparingEntry::origLocation
uint32_t origLocation
Definition: osta_udf.h:188
pd
struct partitionDesc * pd
Definition: wrudf.c:62
readPacket
int readPacket(struct packetbuf *pb)
Definition: wrudf-cdrw.c:411
cdrom_trackinfo
Definition: ide-pc.h:95
newSparingTableEntry
uint32_t newSparingTableEntry(uint32_t original)
Definition: wrudf-cdrw.c:326
getFreePacketBuffer
struct packetbuf * getFreePacketBuffer(uint32_t lbn, uint16_t part)
Definition: wrudf-cdrw.c:509
getNWA
uint32_t getNWA()
Definition: wrudf-cdr.c:35
packetbuf::dirty
uint32_t dirty
Definition: wrudf-cdrw.c:43
cdrom_trackinfo::rsrvd_trk
u_char rsrvd_trk
Definition: ide-pc.h:108
cdrom_writeparams::session_format
u_char session_format
Definition: ide-pc.h:220
ALLOC
Definition: wrudf.h:127
packetbuf::pkt
unsigned char * pkt
Definition: wrudf-cdrw.c:46
usedSparingEntries
unsigned int usedSparingEntries
Definition: wrudf.c:73
DB_ROM_MODE1
#define DB_ROM_MODE1
Definition: ide-pc.h:206
ti
struct cdrom_trackinfo ti
Definition: wrudf-cdrw.c:50
cdrom_discinfo
Definition: ide-pc.h:62