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

📄 growisofs_mmc.cpp

📁 最新的linux下dvd刻录软件,支持DVD+RW、DVD-RW光盘刻录。
💻 CPP
📖 第 1 页 / 共 4 页
字号:
#ifndef _LARGEFILE_SOURCE#define _LARGEFILE_SOURCE#endif#ifndef _LARGEFILE64_SOURCE#define _LARGEFILE64_SOURCE#endif#ifndef _FILE_OFFSET_BITS#define _FILE_OFFSET_BITS 64#endif#if defined(__linux)/* ... and "engage" glibc large file support */#ifndef _GNU_SOURCE#define _GNU_SOURCE#endif#endif#include "transport.hxx"#include <time.h>#include <sys/types.h>#define SIGS_BLOCK	1#define SIGS_UNBLOCK	0extern "C" void sigs_mask (int);extern "C" void atsignals (void (*)(void));#define	DVD_1X	1352	// 1385 * 1000 / 1024#define BD_1X	4390	// 4495.5 * 1000 / 1024static int		media_written=0,next_track=1,			is_dao=0,quickgrown=0,do_reload=1,			_1x=DVD_1X,_64k=0,bdr_plus_pow=0;static unsigned int	stdnap=(256*1000)/DVD_1X,// measured in milliseconds			buf_size=512;		// measured in KBsstatic class __velocity__ {    private:	int value;    public:	int operator=(int v)	{ if (v>=_1x)	stdnap=(buf_size*500)/v;				  else		stdnap=(buf_size*500)/_1x;				  return value = v;				}	operator int()		{ return value; }} velocity;static void         *ioctl_handle=(void *)-1;#ifndef ioctl_fd#define ioctl_fd ((long)ioctl_handle)#endifstatic unsigned int  next_wr_addr=1;	// it starts as booleanstatic unsigned int  dao_blocks=0;static unsigned int  cap2kstart=0;static unsigned char formats[260],disc_info[32];extern "C" {extern int	dvd_compat,test_write,no_reload,mmc_profile,_argc,		wrvfy,no_opc,spare;extern double	speed_factor;extern char	*ioctl_device,**_argv;}extern "C"int __1x (void) { return _1x; }extern "C"int fumount (int fd){ Scsi_Command cmd;  return cmd.umount(fd);}extern "C"int media_reload (char *name=NULL,struct stat *sb=NULL,unsigned int cap2k=0){   if (name==NULL)    {	Scsi_Command cmd(ioctl_handle);	pioneer_stop (cmd);#if defined(RELOAD_NEVER_NEEDED)#undef RELOAD_NEVER_NEEDED#define RELOAD_NEVER_NEEDED 1#else#define RELOAD_NEVER_NEEDED 0#endif	if (RELOAD_NEVER_NEEDED || no_reload>0)	{   cmd[0] = 0x1E;	// ALLOW MEDIA REMOVAL	    cmd[5] = 0;	    cmd.transport ();	    return (errno=0);	}#if !RELOAD_NEVER_NEEDED	char fdstr[12],cap2kstr[12];	int n;		if ((n=fcntl (ioctl_fd,F_GETFD))<0) n=0;	fcntl (ioctl_fd,F_SETFD,n&~FD_CLOEXEC);	sprintf (fdstr,"%ld",ioctl_fd);	sprintf (cap2kstr,"%u",cap2kstart);	execlp(_argv[0],no_reload<0?"-eject":"-reload",			fdstr,ioctl_device,cap2kstr,(void *)NULL);    }    else    {	{ Scsi_Command  cmd;	  unsigned char c[8];	  unsigned int  cap2kend;	    if (!cmd.associate (name,sb)) return 1;	    cmd[0] = 0x25;	// READ CAPACITY	    cmd[9] = 0;	    if (!cmd.transport (READ,c,sizeof(c)))		cap2kend = c[0]<<24|c[1]<<16|c[2]<<8|c[3];	    else		cap2kend = (unsigned int)-1;	    if (cmd.is_reload_needed(cap2k==cap2kend))	    {	fprintf (stderr,"%s: reloading tray\n",name);		cmd[0] = 0x1E;		// ALLOW MEDIA REMOVAL		cmd[5] = 0;		if (cmd.transport ()) return 1;		while (1)	// Pioneer DVR-x05 needs this...		{   cmd[0] = 0x1B;	// START/STOP UNIT		    cmd[1] = 0x1;	// "IMMED"		    cmd[4] = 0x2;	// "Eject"		    cmd[5] = 0;		    if (cmd.transport() == 0x20407) // "OP IN PROGRESS"		    {	poll (NULL,0,333);			continue;		    }		    break;		}		// yes, once again, non-"IMMED"...		cmd[0] = 0x1B;		// START/STOP UNIT		cmd[4] = 0x2;		// "Eject"		cmd[5] = 0;		if (cmd.transport()) return 1;	    }#if defined(__sun) || defined(sun)	    else if (volmgt_running())	    {	setuid(getuid());		execl("/usr/bin/volrmmount","volrmmount","-i",name,(void*)NULL);		return 0;	// not normally reached	    }#endif	    else return 0;	// m-m-m-m! patched kernel:-)	}	if (no_reload>=0)	{ Scsi_Command cmd;	    if (cmd.associate (name,sb))	    {	cmd[0] = 0x1B;		// START/STOP UNIT		cmd[1] = 0x1;		// "IMMED"		cmd[4] = 0x3;		// "Load"		cmd[5] = 0;		cmd.transport ();	    }	    errno=0;	// ignore all errors on load	}	return 0;#endif    }  return 1;}extern "C"int get_mmc_profile (void *fd){ Scsi_Command cmd(fd);  unsigned char buf[8],inq[128];  int profile=0,once=1,blank=0,err;  unsigned int len;  #if defined(__APPLE__) && defined(__MACH__)  // The reason for Mac OS X specific MMCIO appearing here and there  // is that raw SCSI requires exclusive access, while I'm not ready  // to give it up yet...    // I don't call INQUIRY, because kernel ensures that    // MMCDeviceInterface is attached to an MMC device...    if ((err=MMCIO(fd,GetConfiguration,0,0,buf,sizeof(buf))))	sperror ("GET CONFIGURATION",err),	exit (FATAL_START(errno));    profile = buf[6]<<8|buf[7];#else    // INQUIRY is considered to be "non-intrusive" in a sense that    // it won't interfere with any other operation nor clear sense    // data, which might be important to retain for security reasons.    cmd[0] = 0x12;	// INQUIRY    cmd[4] = 36;    cmd[5] = 0;    if ((err=cmd.transport(READ,inq,36)))	sperror ("INQUIRY",err),	exit (FATAL_START(errno));    // make sure we're talking to MMC unit, for security reasons...    if ((inq[0]&0x1F) != 5)	fprintf (stderr,":-( not an MMC unit!\n"),	exit (FATAL_START(EINVAL));    do {	cmd[0] = 0x46;	cmd[8] = sizeof(buf);	cmd[9] = 0;	if ((err=cmd.transport(READ,buf,sizeof(buf))))	    sperror ("GET CONFIGURATION",err),	    fprintf (stderr,":-( non-MMC unit?\n"),	    exit (FATAL_START(errno));        if ((profile = buf[6]<<8|buf[7]) || !once) break;	// no media?	cmd[0] = 0;	// TEST UNIT READY	cmd[5] = 0;	if ((cmd.transport()&0xFFF00) != 0x23A00) break;	// try to load tray...	cmd[0] = 0x1B;	// START/STOP UNIT	cmd[4] = 0x3;	// "Load"	cmd[5] = 0;	if ((err=cmd.transport ()))	    sperror ("LOAD TRAY",err),	    exit (FATAL_START(errno));#if 1	wait_for_unit (cmd);#else	// consume sense data, most likely "MEDIA MAY HAVE CHANGED"	cmd[0] = 0;	// TEST UNIT READY	cmd[5] = 0;	if ((err=cmd.transport ()) == -1)	    sperror ("TEST UNIT READY",err),	    exit (FATAL_START(errno));#endif    } while (once--);#endif	// !Mac OS X    if (profile==0 || (profile&0x70)==0)	// no or non-DVD/BD media...	return profile;    if ((profile&0xF0) == 0x40)    { unsigned char header[16];	_1x = BD_1X;	_64k = 1;	if (profile==0x41)	// BD-R SRM	{   // Check for POW feature...#if defined(__APPLE__) && defined(__MACH__)	    err = MMCIO(fd,GetConfiguration,2,0x38,header,16);#else	    cmd[0] = 0x46;	// GET CONFIGURATION	    cmd[1] = 2;		// ask for the only feature...	    cmd[3] = 0x38;	// the "BD-R Pseudo-Overwrite" one	    cmd[8] = 16;	// The feature should be there, right?	    cmd[9] = 0;	    err = cmd.transport (READ,header,16);#endif	    if (err==0 &&		(header[0]<<24|header[1]<<16|header[2]<<8|header[3])>=12 &&		(header[8+2]&1)==1)		bdr_plus_pow=1;	}    }#if defined(__APPLE__) && defined(__MACH__)    err = MMCIO(fd,ReadDiscInformation,disc_info,sizeof(disc_info));#else    cmd[0] = 0x51;	// READ DISC INFORMATION    cmd[8] = sizeof(disc_info);    cmd[9] = 0;    err = cmd.transport (READ,disc_info,sizeof(disc_info));#endif    if (err)	sperror ("READ DISC INFORMATION",err),	exit (FATAL_START(errno));    // see if it's blank media    if ((disc_info[2]&3) == 0)	blank=0x10000;    if (profile != 0x1A && profile != 0x2A &&		// DVD+RW	profile != 0x13 && profile != 0x12 &&		// DVD-R[AM]	profile != 0x43 && !(profile == 0x41 && blank))	// BD-R[E]	return blank|profile;#if defined(__APPLE__) && defined(__MACH__)    err = MMCIO(fd,ReadFormatCapacities,formats,12);#else    cmd[0] = 0x23;	// READ FORMAT CAPACITIES    cmd[8] = 12;    cmd[9] = 0;    err = cmd.transport (READ,formats,12);#endif    if (err)	sperror ("READ FORMAT CAPACITIES",err),	exit (FATAL_START(errno));    len = formats[3];    if (len&7 || len<16)	fprintf (stderr,":-( FORMAT allocaion length isn't sane"),	exit (FATAL_START(EINVAL));#if defined(__APPLE__) && defined(__MACH__)    err = MMCIO(fd,ReadFormatCapacities,formats,4+len);#else    cmd[0] = 0x23;	// READ FORMAT CAPACITIES    cmd[7] = (4+len)>>8;    cmd[8] = (4+len)&0xFF;    cmd[9] = 0;    err = cmd.transport (READ,formats,4+len);#endif    if (err)	sperror ("READ FORMAT CAPACITIES",err),	exit (FATAL_START(errno));    if (len != formats[3])	fprintf (stderr,":-( parameter length inconsistency\n"),	exit(FATAL_START(EINVAL));    // see if it's not formatted    if ((formats[8]&3) != 2) blank = 0x10000;  return blank|profile;}static unsigned int get_2k_capacity (Scsi_Command &cmd,void *fd=NULL){ unsigned char	buf[32];  unsigned int	ret=0;  unsigned int	nwa,free_blocks;  int		i,obligatory,len,err;    obligatory=0x00;    switch (mmc_profile&0xFFFF)    {	case 0x1A:		// DVD+RW	    obligatory=0x26;	case 0x13:		// DVD-RW Restricted Overwrite	    for (i=8,len=formats[3];i<len;i+=8)		if ((formats [4+i+4]>>2) == obligatory) break;	    if (i==len)	    {	fprintf (stderr,":-( can't locate obligatory format descriptor\n");		return 0;	    }	    ret  = formats[4+i+0]<<24;	    ret |= formats[4+i+1]<<16;	    ret |= formats[4+i+2]<<8;	    ret |= formats[4+i+3];	    nwa = formats[4+5]<<16|formats[4+6]<<8|formats[4+7];	    if (nwa>2048)	ret *= nwa/2048;	    else if (nwa<2048)	ret /= 2048/nwa;	    break;	case 0x12:		// DVD-RAM	    // As for the moment of this writing I don't format DVD-RAM.	    // Therefore I just pull formatted capacity for now...	    ret  = formats[4+0]<<24;	    ret |= formats[4+1]<<16;	    ret |= formats[4+2]<<8;	    ret |= formats[4+3];	    nwa = formats[4+5]<<16|formats[4+6]<<8|formats[4+7];	    if (nwa>2048)	ret *= nwa/2048;	    else if (nwa<2048)	ret /= 2048/nwa;	    break;	case 0x11:		// DVD-R	case 0x14:		// DVD-RW Sequential	case 0x15:		// DVD-R Dual Layer Sequential	case 0x16:		// DVD-R Dual Layer Jump	case 0x1B:		// DVD+R	case 0x2B:		// DVD+R Double Layer	case 0x41:		// BD-R SRM#if defined(__APPLE__) && defined(__MACH__)	    if (fd)		err = MMCIO(fd,ReadTrackInformation,1,next_track,buf,sizeof(buf));	    else#endif	    {	cmd[0] = 0x52;	// READ TRACK INFORMATION		cmd[1] = 1;		cmd[4] = next_track>>8;		cmd[5] = next_track&0xFF;	// last track, set up earlier		cmd[8] = sizeof(buf);		cmd[9] = 0;		err = cmd.transport (READ,buf,sizeof(buf));	    }	    if (err)	    {	sperror ("READ TRACK INFORMATION",err);		return 0;	    }	    nwa = 0;	    if (buf[7]&1 && !bdr_plus_pow)	// NWA_V	    {	nwa  = buf[12]<<24;		nwa |= buf[13]<<16;		nwa |= buf[14]<<8;		nwa |= buf[15];	    }	    free_blocks  = buf[16]<<24;	    free_blocks |= buf[17]<<16;	    free_blocks |= buf[18]<<8;	    free_blocks |= buf[19];	    ret = nwa + free_blocks;	    break;	case 0x43:		// BD-RE	    // just pull formatted capacity for now...	    ret  = formats[4+0]<<24;	    ret |= formats[4+1]<<16;	    ret |= formats[4+2]<<8;	    ret |= formats[4+3];	    break;	default:	    break;    }  return ret;}extern "C"off64_t get_capacity (void *fd){ Scsi_Command	cmd(fd);  return (off64_t)get_2k_capacity(cmd,fd)*2048;}extern "C"float get_buffer_stats (void *fd){ Scsi_Command		cmd(fd);  unsigned char		bcap[12];  unsigned int		bsize,bfree,err;    cmd[0] = 0x5C;              // READ BUFFER CAPACITY    cmd[8] = sizeof(bcap);    cmd[9] = 0;    if ((err=cmd.transport (READ,bcap,sizeof(bcap))))	return -err;    bsize = bcap[4]<<24|bcap[5]<<16|bcap[6]<<8|bcap[7];    bfree = bcap[8]<<24|bcap[9]<<16|bcap[10]<<8|bcap[11];  return bsize ? (1.0 - (float)bfree/(float)bsize) : 0.0;}ssize_t poor_mans_pwrite64 (int fd,const void *_buff,size_t size,off64_t foff){ Scsi_Command		cmd(ioctl_handle);	/* screw first argument */  unsigned char		bcap[12];  const unsigned char  *buff=(const unsigned char *)_buff;  unsigned int		lba,nbl,bsize,bfree;  int			retries=0,errcode;  static int		dao_toggle=-1;    if (foff&0x7FFF || size&0x7FFF)	// 32K block size	return (errno=EINVAL,-1);    lba = foff>>11;    nbl = size>>11;    if (!media_written && next_wr_addr)    {	if ((lba+nbl) <= next_wr_addr)	    return size;	else if (next_wr_addr > lba)	    nbl  -= (next_wr_addr-lba),	    size -= (next_wr_addr-lba)<<11,	    buff += (next_wr_addr-lba)<<11,	    lba   = next_wr_addr;    }#if defined(__sun) || defined(sun)    else    next_wr_addr = lba;#endif    if (dao_toggle<0) dao_toggle=is_dao;    { static unsigned int first_wr_addr=0;	if (!media_written)	{   sigs_mask (SIGS_BLOCK); first_wr_addr = lba;	}	else if (lba >= (first_wr_addr+buf_size/2)) // measured in 2KBs!	{   sigs_mask (SIGS_UNBLOCK);			}    }    if (dao_blocks!=0 && (lba+nbl)>dao_blocks)	nbl = dao_blocks-lba;    while (1)    {	cmd[0] = wrvfy?0x2E:0x2A;	// WRITE [AND VERIFY] (10)	cmd[2] = (lba>>24)&0xff;	// Logical Block Addrss	cmd[3] = (lba>>16)&0xff;	cmd[4] = (lba>>8)&0xff;	cmd[5] = lba&0xff;	cmd[7] = (nbl>>8)&0xff;	cmd[8] = nbl&0xff;	cmd[9] = 0;#if 0	cmd[0] = 0xAA;			// WRITE(12)	cmd[2] = (lba>>24)&0xff;	// Logical Block Addrss	cmd[3] = (lba>>16)&0xff;	cmd[4] = (lba>>8)&0xff;	cmd[5] = lba&0xff;	cmd[8] = (nbl>>8)&0xff;	cmd[9] = nbl&0xff;	cmd[10] = 0x80;			// "Streaming"	cmd[11] = 0;#endif	//	// First writes can be long, especially in DAO mode...	// I wish I could complement this with "if (lba==0),"	// but some units might choose to fill the buffer before	// they take the first nap...	//	cmd.timeout(dao_toggle?180:60);	//	// It should also be noted that under Linux these values	// (if actually respected by kernel!) can turn out bogus.	// The problem is that I scale them to milliseconds as	// documentation requires/implies, while kernel treats	// them as "jiffies." I could/should have used HZ macro	// (or sysconf(_SC_CLK_TCK)), but recent kernels maintain	// own higher HZ value and disrespects the user-land one.	// Sending them down as milliseconds is just safer...	//	if (!(errcode=cmd.transport (WRITE,(void *)buff,size)))	    break;	//--- WRITE failed ---//#if defined(__sun) || defined(sun)	//	// Solaris can slice USB WRITEs to multiple ones. Here I try	// to find out which slice has failed. I expect we get here	// only when we re-enter the loop...	//	if (lba==next_wr_addr &&	    errcode==0x52102)		// "INVALID ADDRESS FOR WRITE"	{ unsigned char track[32];	    cmd[0] = 0x52;		// READ TRACK INFORMATION	    cmd[1] = 1;	    cmd[4] = next_track>>8;	    cmd[5] = next_track&0xFF;	    cmd[8] = sizeof(track);	    cmd[9] = 0;	    if (!cmd.transport (READ,track,sizeof(track)))

⌨️ 快捷键说明

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