⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wrudf-cdrw.c

📁 linux下的DVD格式udf文件读取库
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	wrufd-cdrw.c * * PURPOSE *	Lowlevel IO routines. *	To minimise reading and writing packets wrudf uses a few 64kb packetbuffers. *	Blocks to be read are preferentially taken from those buffers and updates written *	to the buffers. Buffers that are in-use will not be discarded. *	When a new buffer is required preferentially an unused not-dirty buffer gets overwritten. *	If not available, then a unused dirty buffer gets written and is then reused. *	If no such buffer can be found the system panics. *   * CONTACTS *	E-mail regarding this program may be directed to  *		e.fennema@dataweb.nl * * COPYRIGHT *	This file is distributed under the terms of the GNU General Public *	License (GPL). Copies of the GPL can be obtained from: *		ftp://prep.ai.mit.edu/pub/gnu/GPL * *  (C) 2001 Enno Fennema * * HISTORY *  16 Aug 01  ef  Created. */#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <linux/cdrom.h>		/* for CDROM_DRIVE_STATUS  */#include "wrudf.h"#include "ide-pc.h"#include "bswap.h"#define MAXPKTBUFS	4struct packetbuf {    uint32_t		inuse;    uint32_t		dirty;    uint32_t		bufNum;    uint32_t		start;    uint8_t		*pkt;};int			lastTrack;struct cdrom_trackinfo	ti;struct read_error_recovery_params	*rerp;u_char *rerp_buffer;struct cdrom_cacheparams		*cp;u_char *cp_buffer;struct packetbuf pktbuf[MAXPKTBUFS+1];			/* last one special use */uint8_t	*verifyBuffer;					/* for verify only */uint8_t	*blockBuffer;uint32_t	trackStart;uint32_t	trackSize;int	sectortype;					/* from track info for readCD() *//* declarations */struct packetbuf* findBuf(uint32_t blkno);int	readPacket(struct packetbuf* pb);int	writePacket(struct packetbuf* pb);/*	markBlock() *	FREE or ALLOC block in spacemap */void markBlock(enum markAction action, uint32_t blkno) {    uint8_t	*bm;    uint8_t	mask;    spaceMapDirty = 1;    bm = spaceMap->bitmap + (blkno >> 3);    mask = 1 << (blkno & 7);    if( action == FREE ) {	*bm |= mask;	lvid->freeSpaceTable[pd->partitionNumber]++;    } else {	*bm &= ~mask;	lvid->freeSpaceTable[pd->partitionNumber]--;    }}/*	GetExtents() *	Try to find unallocated blocks for 'requestedLength' bytes in the rewriteable partition *	Return short_ad's of lbns in the physical partition together satisfying that request *	Last extent has length < n * 2048; if exact multiple of 2048 the a final length 0 short_ad * *	Return value: lenAllocDescs if extents found, 0 if not. */int getExtents(uint32_t requestedLength, short_ad *extents) {    uint32_t	blkno, lengthFound = 0;    short_ad	*ext;    uint32_t	mask, *bm;    if( medium == CDR ) {	/* check space availability */	extents->extLength = requestedLength;	extents->extPosition = getNWA() -  pd->partitionStartingLocation;	if( (requestedLength & 2047) == 0 ) {	    extents[1].extPosition = 0;	    extents[1].extLength = 0;	    return 16;	} else	    return 8;    }    // clear extents    ext = extents;    ext->extLength = 0;    bm = ((uint32_t*)spaceMap->bitmap) - 1;    mask = 0;    blkno = 0xFFFFFFFF;    while( lengthFound < requestedLength ) {	blkno++;	mask <<= 1;	if( mask == 0 ) {	    bm++;	    mask = 1;	    // check bm within limits	}	if( (*bm & mask) == 0 ) {			// if allocated	    if( ext->extLength != 0 ) {		ext++;		if( ext - extents > 31 ) {		    printf("GetExtents: Too many extents\n");		    return 0;		}		ext->extLength = 0;	    }	    continue;	}	if( ext->extLength == 0 )	    ext->extPosition = blkno;	lengthFound += 2048;	ext->extLength += 2048;    }    if( requestedLength != lengthFound  ) {	ext->extLength = ((ext->extLength & ~2047) | (requestedLength & 2047)) - 2048;    } else {	ext++;	ext->extLength = 0;	ext->extPosition = 0;    }    return (uint8_t*)ext - (uint8_t*)extents + sizeof(short_ad);}intfreeShortExtents(short_ad* extents) {    uint32_t blkno, lengthFreed;    short_ad*	ext;        for( ext = extents; extents->extLength != 0; ext++ ) {	blkno = ext->extPosition;	for( lengthFreed = 0 ; lengthFreed < ext->extLength; lengthFreed += 2048 ) {	    markBlock(FREE, blkno);	    blkno++;	}	if( ext->extLength & 2047 || (ext+1)->extLength == 0 )	    break;    }    return CMND_OK;}	int freeLongExtents(long_ad* extents) {    uint32_t blkno, lengthFreed;    long_ad*	ext;    for( ext = extents; extents->extLength != 0; ext++ ) {	if( ext->extLocation.partitionReferenceNum != pd->partitionNumber )	    fail("freeLongExtents: Not RW partition\n");	blkno = ext->extLocation.logicalBlockNum;	for( lengthFreed = 0 ; lengthFreed < ext->extLength; lengthFreed += 2048 ) {	    markBlock(FREE, blkno);	    blkno++;	}	if( ext->extLength & 2047 || (ext+1)->extLength == 0 )	    break;    }    return CMND_OK;}/*	getUnallocSpaceExtent() *	Only used to get new extent for LVID sequence *	(Could use to extend sparing blocks as well) */void getUnallocSpaceExtent(int requestLength, int requestAfter, extent_ad *alloc) {    int		i, n;    alloc->extLength = alloc->extLocation = 0;    n = (requestLength + 2047) & ~2047;    for( i = 0; i < usd->numAllocDescs; i++ ) {	if( usd->allocDescs[i].extLocation > requestAfter ) {	    if( usd->allocDescs[i].extLength >= requestLength ) {		alloc->extLocation = usd->allocDescs[i].extLocation;		alloc->extLength = n;		usd->allocDescs[i].extLocation += n >> 11;		usd->allocDescs[i].extLength -= n;		usdDirty = 1;		return;	    } else {		alloc->extLocation = usd->allocDescs[i].extLocation;		alloc->extLength = usd->allocDescs[i].extLength;		usd->numAllocDescs--;		for (  ; i < usd->numAllocDescs; i++ )		    usd->allocDescs[i] = usd->allocDescs[i+1];		usdDirty = 1;		return;	    }	}    }    if( requestAfter > 0 )	getUnallocSpaceExtent( requestLength, 0, alloc);}    void setChecksum(void *descriptor) {    uint32_t	sum;    int		i;    tag		*descTag = (tag*) descriptor;    descTag->descCRC = udf_crc((uint8_t*)descTag + sizeof(tag), descTag->descCRCLength, 0);    descTag->tagChecksum = sum = 0;    for( i = 0; i < 16; i++ )	sum += *((uint8_t*)descTag + i);    descTag->tagChecksum = (uint8_t) sum;}void updateTimestamp(time_t t, uint32_t ut) {    struct timeval	timev;    struct tm		time;    int			offset;    if( t == 0 ) {	gettimeofday(&timev, NULL);    } else {	timev.tv_sec = t;	timev.tv_usec = ut;    }    localtime_r( &timev.tv_sec, &time);    offset = time.tm_gmtoff / 60;    timeStamp.typeAndTimezone = 0x1000 + (offset & 0x0FFF);		/* 1/3.7.1 */    timeStamp.year = time.tm_year + 1900;    timeStamp.month = time.tm_mon + 1;;    timeStamp.day = time.tm_mday;    timeStamp.hour = time.tm_hour;    timeStamp.minute = time.tm_min;    timeStamp.second = time.tm_sec;    timeStamp.centiseconds = timev.tv_usec / 10000;    timeStamp.hundredsOfMicroseconds = (timev.tv_usec / 100) % 100;    timeStamp.microseconds = timev.tv_usec % 100 ;}void setStrictRead(int yes) {    if( device == DISK_IMAGE )	return;    synchronize_cache(device);    if( yes ) {	rerp->error_recovery_param = 0x04;	rerp->retry_count = 2;	cp->rcd = 1;    } else {	rerp->error_recovery_param = 0x00;		// back to default	rerp->retry_count = 5;	cp->rcd = 0;    }    mode_select(device, rerp_buffer);    mode_select(device, cp_buffer);}uint32_t	getPhysical(uint32_t lbn, uint16_t part) {    if( part == 0xFFFF ) 	return lbn;    if( part == virtualPartitionNum )	lbn = vat[lbn];    return lbn + pd->partitionStartingLocation;}int cmpBlk(const void* a, const void* b) {		/* compare routine for sparing table lookup */    if( *(uint32_t*)a < ((struct sparingEntry*)b)->origLocation )	return -1;    if( *(uint32_t*)a > ((struct sparingEntry*)b)->origLocation )	return 1;    return 0;}/* 	If the original packet occurs in the Sparing Table return the mappedLocation *	else return the original packet address unchanged. */uint32_t lookupSparingTable(uint32_t original) {    struct sparingEntry* se;    if( !st )					// no sparing table found	return original;    se = bsearch(&original, st->mapEntry, usedSparingEntries, sizeof(struct sparingEntry), cmpBlk);        if( se )	return se->mappedLocation;    else	return original;}/*	Make an entry in the Sparing Table for packet 'original' and *	return the mappedLocation */uint32_t newSparingTableEntry(uint32_t original) {    struct sparingEntry *se, newEntry, swapEntry;    uint32_t	mapped;    int		i;    if( !st ) {	printf("No sparing table provided\n");	return INVALID;    }    if( usedSparingEntries == st->reallocationTableLen ) {	fail("SparingTable full\n");    }	    se = bsearch(&original, &st->mapEntry[0], usedSparingEntries, sizeof(struct sparingEntry), cmpBlk);    if( se ) {					/* sparing a sparing packet */	se->origLocation = 0xFFFFFFF0;    }    newEntry.origLocation = original;    newEntry.mappedLocation = mapped = st->mapEntry[usedSparingEntries].mappedLocation;    for( i = 0; i < usedSparingEntries; i++ ) {	if( st->mapEntry[i].origLocation < original )	    continue;    }    for(   ; i <= usedSparingEntries; i++ ) {	swapEntry = st->mapEntry[i];	st->mapEntry[i] = newEntry;	newEntry = swapEntry;    }    usedSparingEntries++;    st->sequenceNum++;    sparingTableDirty = 1;#ifdef DEBUG    printf("Sparing %d to %d\n", original, mapped);#endif    return mapped;}/*	updateSparingTable() *	Only done when quitting. *	Do not verify writing as that would change the table again. */void updateSparingTable() {    int			i, pbn, stat;    struct generic_desc	*p;    struct packetbuf	*pb;    struct sparablePartitionMap *spm = (struct sparablePartitionMap*)lvd->partitionMaps;    for( i = 0; i <= 4; i++ ) {	pbn = spm->locSparingTable[i];	if( pbn == 0 )	    return;	p = readBlock(pbn, ABSOLUTE);	pb = findBuf(pbn);	memcpy(p, st, sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry));	p->descTag.tagLocation = pbn;	p->descTag.descCRCLength = 	    sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry) - sizeof(tag);	setChecksum(p);	if( devicetype != DISK_IMAGE ) {	    stat = writeCD(device, pbn, 32, pb->pkt);	    if( stat )		printf("Write SparingTable at %d: %s\n", pbn, get_sense_string());	} else { // DISK_IMAGE	    stat= lseek(device, 2048 * pbn, SEEK_SET);	    stat = write(device, pb->pkt, 32 * 2048);	    if( stat < 0 )		fail("writeSparingTable at %d: %m\n", pbn);	}    }}int readPacket(struct packetbuf* pb) {    int		stat;    uint32_t	physical;    physical = lookupSparingTable(pb->start);    if( devicetype != DISK_IMAGE ) {	stat = readCD(device, sectortype, physical, 32, pb->pkt);	if( stat )	    printf("readPacket: readCD %s\n", get_sense_string());    } else {	stat = lseek(device, 2048 * physical, SEEK_SET);	stat = read(device, pb->pkt, 32 * 2048);	if( stat != 32 * 2048 )	    fail("readPacket: read failed %m\n");    }    return stat;}   int writePacket(struct packetbuf* pb) {    int		stat, retry;    uint32_t	physical;    pb->dirty = 0;    physical = lookupSparingTable(pb->start);    if( devicetype != DISK_IMAGE ) {	for(retry = 0; retry < 2; retry++ ) {	    if( retry != 0 )		physical = newSparingTableEntry(pb->start);	    stat = writeCD(device, physical, 32, pb->pkt);	    if( stat )		fail("writePacket: writeCD %s\n", get_sense_string());	    // must now verify write operation and spare if necessary	    // My HP8100 does not support Verify or WriteAndVerify	    // Use ReadCD with strict Read Error Recovery Parameters	    setStrictRead(1);	    stat = readCD(device, sectortype, physical, 32, verifyBuffer);	    if( stat == 0 ) {		setStrictRead(0);		return 0;	    }	    printf("writePacket: verify %s\n", get_sense_string());

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -