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

📄 transport.hxx

📁 linux平台下的dvd刻录软件
💻 HXX
📖 第 1 页 / 共 3 页
字号:
//// This is part of dvd+rw-tools by Andy Polyakov <appro@fy.chalmers.se>//// Use-it-on-your-own-risk, GPL bless...//// For further details see http://fy.chalmers.se/~appro/linux/DVD+RW///#if defined(__unix) || defined(__unix__)#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <poll.h>#include <sys/time.h>inline long getmsecs(){ struct timeval tv;    gettimeofday (&tv,NULL);  return tv.tv_sec*1000+tv.tv_usec/1000;}#include <errno.h>#ifndef EMEDIUMTYPE#define EMEDIUMTYPE	EINVAL#endif#ifndef	ENOMEDIUM#define	ENOMEDIUM	ENODEV#endif#elif defined(_WIN32)#include <windows.h>#include <stdio.h>#define EINVAL		ERROR_BAD_ARGUMENTS#define ENOMEM		ERROR_OUTOFMEMORY#define EMEDIUMTYPE	ERROR_MEDIA_INCOMPATIBLE#define ENOMEDIUM	ERROR_MEDIA_OFFLINE#define ENODEV		ERROR_BAD_COMMAND#define EAGAIN		ERROR_NOT_READY#define ENOSPC		ERROR_DISK_FULL#define EIO		ERROR_NOT_SUPPORTED#define ENXIO		ERROR_GEN_FAILUREstatic class _win32_errno {    public:	operator int()		{ return GetLastError(); }	int operator=(int e)	{ SetLastError(e); return e; }} _sys_errno;#ifdef errno#undef errno#endif#define errno _sys_errnoinline void perror (const char *str){ LPVOID lpMsgBuf;    FormatMessage( 	FORMAT_MESSAGE_ALLOCATE_BUFFER |	FORMAT_MESSAGE_FROM_SYSTEM | 	FORMAT_MESSAGE_IGNORE_INSERTS,	NULL,	GetLastError(),	0, // Default language	(LPTSTR) &lpMsgBuf,	0,	NULL 	);    if (str)	fprintf (stderr,"%s: %s",str,lpMsgBuf);    else	fprintf (stderr,"%s",lpMsgBuf);    LocalFree(lpMsgBuf);}#define poll(a,b,t)	Sleep(t)#define getmsecs()	GetTickCount()#define exit(e)		ExitProcess(e)#endif#define CREAM_ON_ERRNO_NAKED(s)				\    switch ((s)[12])					\    {	case 0x04:	errno=EAGAIN;	break;		\	case 0x20:	errno=ENODEV;	break;		\	case 0x21:	if ((s)[13]==0)	errno=ENOSPC;	\			else		errno=EINVAL;	\			break;				\	case 0x30:	errno=EMEDIUMTYPE;	break;	\	case 0x3A:	errno=ENOMEDIUM;	break;	\    }#define CREAM_ON_ERRNO(s)	do { CREAM_ON_ERRNO_NAKED(s) } while(0)#define	FATAL_START(er)	(0x80|(er))#define ERRCODE(s)	((((s)[2]&0x0F)<<16)|((s)[12]<<8)|((s)[13]))#define	SK(errcode)	(((errcode)>>16)&0xF)#define	ASC(errcode)	(((errcode)>>8)&0xFF)#define ASCQ(errcode)	((errcode)&0xFF)static void sperror (const char *cmd,int err){ int saved_errno=errno;    if (err==-1)	fprintf (stderr,":-( unable to %s: ",cmd);    else	fprintf (stderr,":-[ %s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh]: ",			cmd,SK(err),ASC(err),ASCQ(err));    errno=saved_errno, perror (NULL);}class autofree {    private:	unsigned char *ptr;    public:	autofree()			{ ptr=NULL; }	~autofree()			{ if (ptr) free(ptr); }	unsigned char *operator=(unsigned char *str)					{ return ptr=str; }	operator unsigned char *()	{ return ptr; }};#if defined(__linux)#include <sys/ioctl.h>#include <linux/cdrom.h>#include <mntent.h>#include <sys/wait.h>#include <sys/utsname.h>#include <scsi/sg.h>#if !defined(SG_FLAG_LUN_INHIBIT)# if defined(SG_FLAG_UNUSED_LUN_INHIBIT)#  define SG_FLAG_LUN_INHIBIT SG_FLAG_UNUSED_LUN_INHIBIT# else#  define SG_FLAG_LUN_INHIBIT 0# endif#endif#ifndef CHECK_CONDITION#define CHECK_CONDITION 0x01#endiftypedef enum {	NONE=CGC_DATA_NONE,	// 3		READ=CGC_DATA_READ,	// 2		WRITE=CGC_DATA_WRITE	// 1	     } Direction;#ifdef SG_IOstatic const int Dir_xlate [4] = {	// should have been defined					// private in USE_SG_IO scope,					// but it appears to be too		0,			// implementation-dependent...		SG_DXFER_TO_DEV,	// 1,CGC_DATA_WRITE		SG_DXFER_FROM_DEV,	// 2,CGC_DATA_READ		SG_DXFER_NONE	};	// 3,CGC_DATA_NONEstatic const class USE_SG_IO {private:    int	yes_or_no;public:    USE_SG_IO()	{ struct utsname buf;		    uname (&buf);		    // was CDROM_SEND_PACKET declared dead in 2.5?		    yes_or_no=(strcmp(buf.release,"2.5.43")>=0);		}    ~USE_SG_IO(){}    operator int()			const	{ return yes_or_no; }    int operator[] (Direction dir)	const	{ return Dir_xlate[dir]; }} use_sg_io;#endifclass Scsi_Command {private:    int fd,autoclose;    char *filename;    struct cdrom_generic_command cgc;    union {	struct request_sense	s;	unsigned char		u[18];    } _sense;#ifdef SG_IO    struct sg_io_hdr		sg_io;#else    struct { int cmd_len,timeout; }	sg_io;#endifpublic:    Scsi_Command()	{ fd=-1, autoclose=1; filename=NULL; }    Scsi_Command(int f)	{ fd=f,  autoclose=0; filename=NULL; }    Scsi_Command(void*f){ fd=(long)f, autoclose=0; filename=NULL; }    ~Scsi_Command()	{ if (fd>=0 && autoclose) close(fd),fd=-1;			  if (filename) free(filename),filename=NULL;			}    int associate (const char *file,const struct stat *ref=NULL)    { struct stat sb;	/*	 * O_RDWR is expected to provide for none set-root-uid	 * execution under Linux kernel 2.6[.8]. Under 2.4 it	 * falls down to O_RDONLY...	 */	if ((fd=open (file,O_RDWR|O_NONBLOCK)) < 0 &&	    (fd=open (file,O_RDONLY|O_NONBLOCK)) < 0)	return 0;	if (fstat(fd,&sb) < 0)				return 0;	if (!S_ISBLK(sb.st_mode))	{ errno=ENOTBLK;return 0; }	if (ref && (!S_ISBLK(ref->st_mode) || ref->st_rdev!=sb.st_rdev))	{   errno=ENXIO; return 0;   }	filename=strdup(file);	return 1;    }    unsigned char &operator[] (size_t i)    {	if (i==0)	{   memset(&cgc,0,sizeof(cgc)), memset(&_sense,0,sizeof(_sense));	    cgc.quiet = 1;	    cgc.sense = &_sense.s;#ifdef SG_IO	    if (use_sg_io)	    {	memset(&sg_io,0,sizeof(sg_io));		sg_io.interface_id= 'S';		sg_io.mx_sb_len	= sizeof(_sense);		sg_io.cmdp	= cgc.cmd;		sg_io.sbp	= _sense.u;		sg_io.flags	= SG_FLAG_LUN_INHIBIT|SG_FLAG_DIRECT_IO;	    }#endif	}	sg_io.cmd_len = i+1;	return cgc.cmd[i];    }    unsigned char &operator()(size_t i)	{ return _sense.u[i]; }    unsigned char *sense()		{ return _sense.u;    }    void timeout(int i)			{ cgc.timeout=sg_io.timeout=i*1000; }#ifdef SG_IO    size_t residue()			{ return use_sg_io?sg_io.resid:0; }#else    size_t residue()			{ return 0; }#endif    int transport(Direction dir=NONE,void *buf=NULL,size_t sz=0)    { int ret = 0;#ifdef SG_IO#define KERNEL_BROKEN 0	if (use_sg_io)	{   sg_io.dxferp		= buf;	    sg_io.dxfer_len		= sz;	    sg_io.dxfer_direction	= use_sg_io[dir];	    if (ioctl (fd,SG_IO,&sg_io)) return -1;#if !KERNEL_BROKEN	    if ((sg_io.info&SG_INFO_OK_MASK) != SG_INFO_OK)#else	    if (sg_io.status)#endif	    {	errno=EIO; ret=-1;#if !KERNEL_BROKEN		if (sg_io.masked_status&CHECK_CONDITION)#endif		{   ret = ERRCODE(sg_io.sbp);		    if (ret==0) ret=-1;		    else	CREAM_ON_ERRNO(sg_io.sbp);		}	    }	    return ret;	}	else#undef KERNEL_BROKEN#endif	{   cgc.buffer		= (unsigned char *)buf;	    cgc.buflen		= sz;	    cgc.data_direction	= dir;	    if (ioctl (fd,CDROM_SEND_PACKET,&cgc))	    {	ret = ERRCODE(_sense.u);		if (ret==0) ret=-1;	    }	}	return ret;    }    int umount(int f=-1)    { struct stat    fsb,msb;      struct mntent *mb;      FILE          *fp;      pid_t          pid,rpid;      int            ret=0,rval;	if (f==-1) f=fd;	if (fstat (f,&fsb) < 0)				return -1;	if ((fp=setmntent ("/proc/mounts","r"))==NULL)	return -1;	while ((mb=getmntent (fp))!=NULL)	{   if (stat (mb->mnt_fsname,&msb) < 0) continue; // corrupted line?	    if (msb.st_rdev == fsb.st_rdev)	    {	ret = -1;		if ((pid = fork()) == (pid_t)-1)	break;		if (pid == 0) execl ("/bin/umount","umount",mb->mnt_dir,NULL);		while (1)		{   rpid = waitpid (pid,&rval,0);		    if (rpid == (pid_t)-1)		    {	if (errno==EINTR)	continue;			else			break;		    }		    else if (rpid != pid)		    {	errno = ECHILD;			break;		    }		    if (WIFEXITED(rval))		    {	if (WEXITSTATUS(rval) == 0) ret=0;			else			    errno=EBUSY; // most likely			break;		    }		    else		    {	errno = ENOLINK;	// some phony errno			break;		    }		}		break;	    }	}	endmntent (fp);	return ret;    }    int is_reload_needed ()    {	return ioctl (fd,CDROM_MEDIA_CHANGED,CDSL_CURRENT) == 0;   }};#elif defined(__OpenBSD__) || defined(__NetBSD__)#include <sys/ioctl.h>#include <sys/scsiio.h>#include <sys/wait.h>#include <sys/param.h>#include <sys/mount.h>typedef off_t off64_t;#define stat64   stat#define fstat64  fstat#define open64   open#define pread64	 pread#define pwrite64 pwrite#define lseek64  lseektypedef enum {	NONE=0,		READ=SCCMD_READ,		WRITE=SCCMD_WRITE	     } Direction;class Scsi_Command {private:    int fd,autoclose;    char *filename;    scsireq_t req;public:    Scsi_Command()	{ fd=-1, autoclose=1; filename=NULL; }    Scsi_Command(int f)	{ fd=f,  autoclose=0; filename=NULL; }    Scsi_Command(void*f){ fd=(long)f, autoclose=0; filename=NULL; }    ~Scsi_Command()	{ if (fd>=0 && autoclose) close(fd),fd=-1;			  if (filename) free(filename),filename=NULL;			}    int associate (const char *file,const struct stat *ref=NULL)    { struct stat sb;	fd=open(file,O_RDWR|O_NONBLOCK);	// this is --^^^^^^-- why we have to run set-root-uid...	if (fd < 0)					return 0;	if (fstat(fd,&sb) < 0)				return 0;	if (!S_ISCHR(sb.st_mode))	{ errno=EINVAL; return 0; }	if (ref && (!S_ISCHR(ref->st_mode) || ref->st_rdev!=sb.st_rdev))	{   errno=ENXIO; return 0;   }	filename=strdup(file);	return 1;    }    unsigned char &operator[] (size_t i)    {	if (i==0)	{   memset(&req,0,sizeof(req));	    req.flags = SCCMD_ESCAPE;	    req.timeout = 30000;	    req.senselen = 18; //sizeof(req.sense);	}	req.cmdlen = i+1;	return req.cmd[i];    }    unsigned char &operator()(size_t i)	{ return req.sense[i]; }    unsigned char *sense()		{ return req.sense;    }    void timeout(int i)			{ req.timeout=i*1000; }    size_t residue()			{ return req.datalen-req.datalen_used; }    int transport(Direction dir=NONE,void *buf=NULL,size_t sz=0)    { int ret=0;	req.databuf = (caddr_t)buf;	req.datalen = sz;	req.flags |= dir;	if (ioctl (fd,SCIOCCOMMAND,&req) < 0)	return -1;	if (req.retsts==SCCMD_OK)		return 0;	errno=EIO; ret=-1;	if (req.retsts==SCCMD_SENSE)	{   ret = ERRCODE(req.sense);	    if (ret==0) ret=-1;	    else	CREAM_ON_ERRNO(req.sense);	}	return ret;    }    // this code is basically redundant... indeed, we normally want to    // open device O_RDWR, but we can't do that as long as it's mounted.    // in other words, whenever this routine is invoked, device is not    // mounted, so that it could as well just return 0;    int umount(int f=-1)    { struct stat    fsb,msb;      struct statfs *mntbuf;      int            ret=0,mntsize,i;	if (f==-1) f=fd;	if (fstat (f,&fsb) < 0)				return -1;	if ((mntsize=getmntinfo(&mntbuf,MNT_NOWAIT))==0)return -1;	for (i=0;i<mntsize;i++)	{ char rdev[MNAMELEN+1],*slash,*rslash;	    mntbuf[i].f_mntfromname[MNAMELEN-1]='\0';	// paranoia	    if ((slash=strrchr (mntbuf[i].f_mntfromname,'/'))==NULL) continue;	    strcpy (rdev,mntbuf[i].f_mntfromname); // rdev is 1 byte larger!	    rslash = strrchr  (rdev,'/');	    *(rslash+1) = 'r', strcpy (rslash+2,slash+1);	    if (stat (rdev,&msb) < 0) continue;	    if (msb.st_rdev == fsb.st_rdev)	    {	ret=unmount (mntbuf[i].f_mntonname,0);		break;            }	}	return ret;    }    int is_reload_needed ()    {	return 1;   }};#elif defined(__FreeBSD__)#include <sys/ioctl.h>#include <camlib.h>#include <cam/scsi/scsi_message.h>#include <cam/scsi/scsi_pass.h>#include <sys/wait.h>#include <sys/param.h>#include <sys/mount.h>#include <dirent.h>typedef off_t off64_t;#define stat64   stat#define fstat64  fstat#define open64   open#define pread64  pread#define pwrite64 pwrite#define lseek64  lseek#define ioctl_fd (((struct cam_device *)ioctl_handle)->fd)typedef enum {	NONE=CAM_DIR_NONE,		READ=CAM_DIR_IN,		WRITE=CAM_DIR_OUT	     } Direction;class Scsi_Command {private:    int fd,autoclose;    char *filename;    struct cam_device  *cam;    union ccb		ccb;public:    Scsi_Command()    {	cam=NULL, fd=-1, autoclose=1; filename=NULL;   }    Scsi_Command(int f)    {	char pass[32];	// periph_name is 16 chars long	cam=NULL, fd=-1, autoclose=1, filename=NULL;	memset (&ccb,0,sizeof(ccb));	ccb.ccb_h.func_code = XPT_GDEVLIST;	if (ioctl (f,CAMGETPASSTHRU,&ccb) < 0) return;	sprintf (pass,"/dev/%.15s%u",ccb.cgdl.periph_name,ccb.cgdl.unit_number);	cam=cam_open_pass (pass,O_RDWR,NULL);    }    Scsi_Command(void *f)    {	cam=(struct cam_device *)f, autoclose=0; fd=-1; filename=NULL;  }    ~Scsi_Command()    {	if (cam && autoclose)	cam_close_device(cam), cam=NULL;	if (fd>=0)		close(fd);	if (filename)		free(filename), filename=NULL;    }    int associate (const char *file,const struct stat *ref=NULL)    {	struct stat sb;	char pass[32];		// periph_name is 16 chars long	fd=open(file,O_RDONLY|O_NONBLOCK);	// all if (ref) code is actually redundant, it never runs	// as long as RELOAD_NEVER_NEEDED...	if (ref && fd<0 && errno==EPERM)	{   // expectedly we would get here if file is /dev/passN	    if (stat(file,&sb) < 0)		return 0;	    if (!S_ISCHR(ref->st_mode) || ref->st_rdev!=sb.st_rdev)		return (errno=ENXIO,0);	    fd=open(file,O_RDWR);	}	if (fd < 0)				return 0;	if (fstat(fd,&sb) < 0)			return 0;	if (!S_ISCHR(sb.st_mode))		return (errno=EINVAL,0);	if (ref && (!S_ISCHR(ref->st_mode) || ref->st_rdev!=sb.st_rdev))	    return (errno=ENXIO,0);	memset (&ccb,0,sizeof(ccb));	ccb.ccb_h.func_code = XPT_GDEVLIST;	if (ioctl(fd,CAMGETPASSTHRU,&ccb)<0)	return (close(fd),fd=-1,0);	sprintf (pass,"/dev/%.15s%u",ccb.cgdl.periph_name,ccb.cgdl.unit_number);	cam=cam_open_pass (pass,O_RDWR,NULL);	if (cam==NULL)				return (close(fd),fd=-1,0);	filename=strdup(file);	return 1;    }    unsigned char &operator[] (size_t i)

⌨️ 快捷键说明

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