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

📄 wrudf-cmnd.c

📁 linux下的DVD格式udf文件读取库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 	wrudf-cmnd.c * * PURPOSE *	High level wrudf command functions * * CONTACTS *	E-mail regarding this program 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 <stddef.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <string.h>#include <unistd.h>#include <dirent.h>#include <sys/stat.h>#include "wrudf.h"int	deleteDirectory(Directory *dir, struct fileIdentDesc *fid);Directory *makeDir(Directory *dir, char* name);int	questionOverwrite(Directory *dir, struct fileIdentDesc *fid, char* name);int	directoryIsEmpty(Directory *dir);char	*hdWorkingDir;/*	copyFile() *	Write File Entry immediately followed by data *	A verify error on CDR causes a further packet with *	the new FE followed by copies of the defective blocks only */intcopyFile(Directory *dir, char* inName, char*newName, struct stat *fileStat) {    int		fd, i, blkno;    uint32_t	nBytes, blkInPkt;    uint32_t	maxVarPktSize;		// in bytes    struct fileIdentDesc *fid;    struct fileEntry *fe;    uint8_t	p[2048];    fd = open(inName, O_RDONLY);    if( fd == 0 ) {	printf("'%s' does not exist\n", cmndv[i]);	return CMND_FAILED;    }    printf("Copy file %s\n", inName);    fid = findFileIdentDesc(dir, newName);    if( fid  && questionOverwrite(dir, fid, newName) )	return CMND_OK;    fid = makeFileIdentDesc(newName);				// could reuse FID if overwrite allowed	        fe = makeFileEntry();    fe->uid = fileStat->st_uid;    fe->gid = fileStat->st_gid;    if( fileStat->st_mode & S_IRUSR ) fe->permissions |= FE_PERM_U_READ;    if( fileStat->st_mode & S_IWUSR ) fe->permissions |= FE_PERM_U_WRITE | FE_PERM_U_DELETE | FE_PERM_U_CHATTR;;    if( fileStat->st_mode & S_IXUSR ) fe->permissions |= FE_PERM_U_EXEC;    if( fileStat->st_mode & S_IRGRP ) fe->permissions |= FE_PERM_G_READ;    if( fileStat->st_mode & S_IWGRP ) fe->permissions |= FE_PERM_G_WRITE | FE_PERM_G_DELETE | FE_PERM_G_CHATTR;    if( fileStat->st_mode & S_IXGRP ) fe->permissions |= FE_PERM_G_EXEC;    if( fileStat->st_mode & S_IROTH ) fe->permissions |= FE_PERM_O_READ;    if( fileStat->st_mode & S_IWOTH ) fe->permissions |= FE_PERM_O_WRITE | FE_PERM_O_DELETE | FE_PERM_O_CHATTR;;    if( fileStat->st_mode & S_IXOTH ) fe->permissions |= FE_PERM_O_EXEC;    if( fileStat->st_mode & S_ISUID ) fe->icbTag.flags |= ICBTAG_FLAG_SETUID;    if( fileStat->st_mode & S_ISGID ) fe->icbTag.flags |= ICBTAG_FLAG_SETGID;    fe->informationLength = fileStat->st_size;    updateTimestamp(fileStat->st_atime, 0);    fe->accessTime = timeStamp;    updateTimestamp(fileStat->st_mtime, 0);    fe->modificationTime = timeStamp;    updateTimestamp(fileStat->st_ctime, 0);    fe->attrTime = timeStamp;    /* check whether embedding of data is possible  */    fe->logicalBlocksRecorded = ((fileStat->st_size + 2047) & ~2047) >> 11;    if( medium == CDR ) {	/*	File data written in physical space but fileEntry in virtual space	 *	so must use long allocation descriptors	 *	 *	Variable packet length restricted by drive buffer size.	 *	Must break up long file over several var packets.	 *	Only 116 long_ad's fit in fileEntry without going to extended alloc descs	 */	long_ad	*ad;	uint32_t	loc;	maxVarPktSize = getMaxVarPktSize();		if( fe->informationLength / maxVarPktSize > 116 ) {	    printf("Cannot handle files longer than %d\n", 116 * maxVarPktSize);	    return CMND_FAILED;	}	fe->icbTag.flags |= ICBTAG_FLAG_AD_LONG;	/* +1 as the fileEntry itself occupies block NWA */	loc = getNWA() + 1 - pd->partitionStartingLocation;	nBytes = (uint32_t) fe->informationLength ;	for( ad = (long_ad*)(fe->allocDescs + fe->lengthExtendedAttr); nBytes > 0; ad++ ) {	    if( nBytes > maxVarPktSize ) {		ad->extLength = maxVarPktSize;		nBytes -= maxVarPktSize;	    } else {		ad->extLength = nBytes;		nBytes = 0;	    }	    ad->extLocation.logicalBlockNum = loc;	    ad->extLocation.partitionReferenceNum = pd->partitionNumber;	    *(uint32_t*)&((struct allocDescImpUse*)(ad->impUse))->impUse = (uint32_t) fe->uniqueID;	    loc += ((ad->extLength + 2047) >> 11) + 7;	}	if( ((ad-1)->extLength & 2047) == 0 ) {	    memset(ad, 0, sizeof(long_ad));	    *(uint32_t*)&((struct allocDescImpUse*)(ad->impUse))->impUse = (uint32_t) fe->uniqueID;	    ad++;	}	fe->lengthAllocDescs = (uint8_t*)ad - (fe->allocDescs + fe->lengthExtendedAttr);	fe->descTag.descCRCLength = sizeof(struct fileEntry) + 	    fe->lengthExtendedAttr + fe->lengthAllocDescs - sizeof(tag);	fe->descTag.tagLocation = newVATentry();	for( ;; ) {	    					/* retry loop for verify failure */	    int		blknoFE, skipped, retries;	    long_ad	*extent;	    setChecksum(fe);	    skipped = 0;	    retries = 0;	    lseek(fd, 0, SEEK_SET);	    /* write FE */	    blknoFE = vat[fe->descTag.tagLocation] = writeCDR(fe) - pd->partitionStartingLocation;	    fid->icb.extLocation.logicalBlockNum = fe->descTag.tagLocation; 	    fid->icb.extLocation.partitionReferenceNum = virtualPartitionNum;	    /* write file data */	    extent = (long_ad*)(fe->allocDescs + fe->lengthExtendedAttr);	    for( blkInPkt = nBytes = 0; nBytes < fe->informationLength; extent++ ) {		blkno = extent->extLocation.logicalBlockNum;		if( blkno < blknoFE ) {		    nBytes += extent->extLength;		    skipped = 1;		    continue;		}		for( i = 0; i < extent->extLength; blkno++, i += 2048 ) {		    memset(p, 0, 2048);		    if( skipped ) {			lseek(fd, nBytes, SEEK_SET);			skipped = 0;		    }		    nBytes += read(fd, p, 2048);		    writeCDR(p);		    if( ++blkInPkt == (maxVarPktSize >> 11) ) {			syncCDR();			blkInPkt = 0;		    }		}		    }	    syncCDR();	    if( verifyCDR(fe) == 0 ) 			// verify the file data		break;	    if( retries++ > 3 ) {		printf("Retry count 3 exceeded\n");		break;	    }	}    } else {	short_ad	*extent, extentFE[2];	if( getExtents(2048, extentFE ) != 16 ) {		/* extent for File Entry */	    printf("No space for File Entry\n");	    return CMND_FAILED;	}	fe->descTag.tagLocation = extentFE[0].extPosition;	// must mark allocated; otherwise allocated for a second time before being written	markBlock(ALLOC, fe->descTag.tagLocation);	fe->lengthAllocDescs = 					/* extents for the file data */	    getExtents(fe->informationLength, (short_ad*)(fe->allocDescs + fe->lengthExtendedAttr));	if( !fe->lengthAllocDescs ) {	    printf("No space for file\n");	    return CMND_FAILED;	}	/* write FE */	fe->descTag.descCRCLength = sizeof(struct fileEntry) + 	    fe->lengthExtendedAttr + fe->lengthAllocDescs - sizeof(tag);	setChecksum(fe);	writeBlock(fe->descTag.tagLocation, pd->partitionNumber, fe);	fid->icb.extLocation.logicalBlockNum = fe->descTag.tagLocation;	fid->icb.extLocation.partitionReferenceNum = pd->partitionNumber;	/* write file data */	extent = (short_ad*)(fe->allocDescs + fe->lengthExtendedAttr);	for( nBytes = 0; nBytes < fe->informationLength; extent++ ) {	    blkno = extent->extPosition;	    for( i = 0; i < extent->extLength; blkno++, i += 2048 ) {		memset(p, 0, 2048);		nBytes += read(fd, p, 2048);		writeBlock(blkno, pd->partitionNumber, p);	    }		}    }    if( devicetype == DISK_IMAGE && medium == CDR )	writeHDlink();    *(uint32_t*)(&( (struct allocDescImpUse*)fid->icb.impUse)->impUse) = (uint32_t) fe->uniqueID;    insertFileIdentDesc(dir, fid);    ((struct logicalVolIntegrityDescImpUse*)	(lvid->impUse + 2 * sizeof(uint32_t) * lvid->numOfPartitions))->numFiles++;    close(fd);    free(fe);    free(fid);    return CMND_OK;}intcopyDirectory(Directory *dir, char* name) {    DIR		*srcDir;    Directory	*workDir;    struct dirent *dirEnt;    struct stat dirEntStat;    struct fileIdentDesc *fid;    if( !(srcDir = opendir(name)) ) {	printf("Open dir '%s': %m\n", name);	return CMND_FAILED;    }    chdir(name);    printf("Now in %s\n", getcwd(NULL, 0));    workDir = dir;    while( (dirEnt = readdir(srcDir)) ) {	if( !strcmp(dirEnt->d_name, ".") || !strcmp(dirEnt->d_name, "..") )	    continue;		lstat(dirEnt->d_name, &dirEntStat);		// do not follow links	if( S_ISDIR(dirEntStat.st_mode) ) {	    if( !(options & OPT_RECURSIVE) ) {		printf("Not recursive. Ignoring '%s' directory\n", dirEnt->d_name);		continue;	    }	    fid = findFileIdentDesc(dir, dirEnt->d_name);	    if( fid  && !(fid->fileCharacteristics & FID_FILE_CHAR_DIRECTORY ) ) {		printf("'%s' exists but is not a directory\n", dirEnt->d_name);		continue;	    }	    if( fid && (fid->fileCharacteristics & FID_FILE_CHAR_DELETED) ) {		removeFID(dir, fid);		fid = NULL;	    }	    if( !fid )		workDir = makeDir(dir, dirEnt->d_name);	    else		workDir = readDirectory(dir, &fid->icb, dirEnt->d_name);	    copyDirectory(workDir, dirEnt->d_name);	} else {	    if( S_ISREG(dirEntStat.st_mode) )		copyFile(workDir, dirEnt->d_name, dirEnt->d_name, &dirEntStat);	}    }    chdir("..");    closedir(srcDir);    return CMND_OK;}/*	deleteDirectory() * *	Recursing into subdirectories. *	If anywhere no permission, query deletion but proceed if 'yes' *	Returns 0 if fid freed, 1 if fid not empty */int deleteDirectory(Directory *dir, struct fileIdentDesc* fid) {    int			i, rv, notEmpty;    char		*name;    struct fileIdentDesc *childFid;    Directory		*childDir;        rv = 0;    if( fid->fileCharacteristics & FID_FILE_CHAR_DELETED ) 	return CMND_OK;    if( (fid->fileCharacteristics & FID_FILE_CHAR_DIRECTORY) == 0 ) 	return deleteFID(dir, fid);			/* delete regular files */    name = malloc(fid->lengthFileIdent + 1);    strncpy(name, fid->fileIdent + fid->lengthOfImpUse, fid->lengthFileIdent);    readDirectory(dir, &fid->icb, name);    childDir = dir->child;    /* check permission */    notEmpty = 0;    for( i = 0; i < childDir->fe.informationLength;	 i += ((sizeof(struct fileIdentDesc) + childFid->lengthOfImpUse + childFid->lengthFileIdent + 3) & ~3) )     {	childFid = (struct fileIdentDesc*)(childDir->data + i);	if( childFid->fileCharacteristics & (FID_FILE_CHAR_DELETED | FID_FILE_CHAR_PARENT) ) 	    continue;	if( childFid->fileCharacteristics & FID_FILE_CHAR_DIRECTORY )	    deleteDirectory( childDir, childFid);	else	    deleteFID(childDir, childFid);    }    if( directoryIsEmpty(childDir) ) {	rv |= deleteFID(dir, fid);    } else {	childDir->dirDirty = 1;	updateDirectory(childDir);	rv = notEmpty;    }    free(name);    return rv;}/*	readDirectory() *	All fileIdentDesc's are put into the data area of the Directory structure.

⌨️ 快捷键说明

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