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

📄 growisofs.c

📁 linux平台下的dvd刻录软件
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (!S_ISCHR(sb.st_mode))    {	if (S_ISBLK(sb.st_mode) && !strncmp (device,"/dev/dsk",7))	{   fprintf (stderr,":-) you most likely want to use "			    "/dev/r%s instead!\n",device+5);	    if (isatty(0) && !dry_run) poll(NULL,0,5000);	}      open_rw:	setuid(uid);	/* drop all privileges	*/	close (in_fd);	/* reopen as mortal	*/	if ((in_fd = open64 (device,O_RDONLY)) < 0)	    fprintf (stderr,":-( unable to reopen(\"%s\",O_RDONLY): ",device),	    perror (NULL), exit (FATAL_START(errno));	if ((out_fd = open64 (device,O_RDWR)) < 0)	    fprintf (stderr,":-( unable to open(\"%s\",O_RDWR): ",device),	    perror (NULL), exit (FATAL_START(errno));      opened_rw:	poor_man = 0;	close (ioctl_fd);	ioctl_handle = INVALID_HANDLE;	setuid (uid);	/* drop all privileges	*/	return device;    }    /*     * Still as euid=root! But note that get_mmc_profile makes sure it's     * an MMC device, as it terminates the program if the unit doesn't     * reply to GET CONFIGURATON. In combination with following switch     * this means that if installed set-root-uid, growisofs grants     * access to DVD burner(s), but not to any other device.     */  tray_might_be_open:    if ((in_fd<0) ? attr_get (device,"_devname",hw_path,&hw_len,0) :		    attr_getf (in_fd,"_devname",hw_path,&hw_len,0) )	fprintf (stderr,":-( unable to obtain hw_path for \"%s\": ",device),	perror (NULL), exit (FATAL_START(errno));    if (hw_len>=sizeof(hw_path)) hw_len=sizeof(hw_path)-1; /* paranoia */    hw_path[hw_len]='\0';    if ((s=strstr(hw_path,"/scsi_ctlr/")))	sscanf (s,"/scsi_ctlr/%d/target/%d/lun/%d/",&bus,&tgt,&lun);    /* Make sure user is using /dev/rdsk/dksXdYlZvol... */    if ((s=strstr(hw_path,"/disk/volume/char"))==NULL)    {   if (lun)	    fprintf (stderr,":-( stick to /dev/rdsk/dks%dd%dl%dvol!\n",			    bus,tgt,lun);	else	    fprintf (stderr,":-( stick to /dev/rdsk/dks%dd%dvol!\n",			    bus,tgt);	exit(FATAL_START(EINVAL));    }    memcpy (s,"/scsi",6);    ioctl_handle = (void *)(long)open64 (hw_path,O_RDWR);    if (ioctl_handle == INVALID_HANDLE)	fprintf (stderr,":-( unable to open(\"%s\",O_RDWR): ",hw_path),	perror (NULL), exit (FATAL_START(errno));    if (fstat64 (ioctl_fd,&sc) < 0)	fprintf (stderr,":-( unable to stat(\"%s\"): ",hw_path),	perror (NULL), exit (FATAL_START(errno));    memcpy (s,"/disk/volume/char",6);    mmc_profile = get_mmc_profile (ioctl_handle);    switch (mmc_profile&0xFFFF)    {	case 0x11:	/* DVD-R			*/	case 0x13:	/* DVD-RW Restricted Overwrite	*/	case 0x14:	/* DVD-RW Sequential		*/	case 0x1A:	/* DVD+RW			*/	case 0x1B:	/* DVD+R			*/	case 0x2B:	/* DVD+R Double Layer		*/	open_poor_man:	    poor_man = 1;	    out_fd = dup (ioctl_fd);	    if (in_fd<0 && (in_fd=open64 (hw_path,O_RDONLY))<0)		/* hope for the best? */ ;	    setuid (uid);	/* drop all privileges	*/	    mediad_get_exclusiveuse (hw_path,"growisofs");	    if (mediad_last_error ()==RMED_NOERROR)		putenv ("MEDIAD_GOT_EXCLUSIVEUSE=");	/* kludge... */	    sprintf (rscsi,"/dev/scsi/sc%dd%dl%d",bus,tgt,lun);	    return ioctl_device=rscsi;	/* might be bogus... */	case 0x12:	/* DVD-RAM			*/	    /* Some of latest tentative IRIX releases seem to	     * implement DVD-RAM writing at dksc level, but I'm	     * not sure which one. So I just fall down to poor-man,	     * at least for now... */	    goto open_poor_man;	    break;	default:	    fprintf (stderr,":-( %s: media is not recognized as "			    "recordable DVD: %X\n",device,mmc_profile);	    exit (FATAL_START(EMEDIUMTYPE));    }    /* not actually reached */    setuid(uid);    goto open_rw;}#else#error "Unsupported OS"#endifint setup_C_parm (char *C_parm,struct iso_primary_descriptor *descr){ int next_session=-1,profile=mmc_profile&0xFFFF;    if (!poor_man || profile==0x1A || profile==0x13 || profile==0x12)    {	next_session = from_733(descr->volume_space_size);	/* pad to closest 32K boundary */	next_session += 15;	next_session /= 16;	next_session *= 16;	sprintf (C_parm,"16,%u",next_session);    }    else if (profile==0x2B || profile==0x1B || profile==0x11 || profile==0x14)	next_session=plusminus_r_C_parm (ioctl_handle,C_parm);  return next_session;}int builtin_dd (int infd,int outfd,off64_t outoff){ char		*s;  int		 n,fd;  unsigned int	 off;  struct stat64  sb;  off64_t	 capacity=0,tracksize=0,startoff=outoff;  pid_t		 pid=(pid_t)-1,ppid=getpid();  volatile struct { time_t zero; off64_t current,final; } *progress;    if ((fd=mkstemp (s=strdup("/tmp/dvd+rw.XXXXXX"))) < 0)	fprintf (stderr,":-( unable to mkstemp(\"%s\")",s),	exit(FATAL_START(errno));    ftruncate(fd,(off_t)sizeof(*progress));    unlink(s), free(s);    progress = (void *)mmap (NULL,sizeof(*progress),PROT_READ|PROT_WRITE,			MAP_SHARED,fd,(off_t)0);    close (fd);    if (progress == MAP_FAILED)	fprintf (stderr,":-( unable to anonymously mmap %lu?\n",			sizeof(*progress)),	perror (NULL), exit(FATAL_START(errno));    if (fstat64 (infd,&sb))	perror (":-( unable to fstat64"), exit(FATAL_START(errno));    if (ioctl_handle!=INVALID_HANDLE)	capacity = get_capacity (ioctl_handle);    progress->zero=0;    progress->current=outoff;    if (dao_size || S_ISREG(sb.st_mode))    {	tracksize = dao_size ? (dao_size*CD_BLOCK) : sb.st_size;	progress->final=outoff+tracksize;	if (capacity && progress->final > capacity)	{   fprintf (stderr,":-( %s: %lld blocks are free, "			    "%lld to be written!\n",			    ioctl_device,			    (capacity-outoff)/2048,tracksize/2048);	    if (overburn)		fprintf (stderr,":-! ignoring...\n");	    else		close(infd), close(outfd),		exit (FATAL_START(ENOSPC));	}    }    else progress->final=0;    if (!dry_run && quiet<=0 && (pid=fork()) == 0)    { double		ratio,velocity,slept;      int		delta,nfirst=0;      off64_t		lastcurrent=outoff,current;      struct timeval	tv;	close (infd);	close (outfd);	while (kill (ppid,0)==0)	{   gettimeofday (&tv,NULL); slept =  tv.tv_usec/1e6+tv.tv_sec;	    lastcurrent = progress->current;	    poll (NULL,0,3333);	    gettimeofday (&tv,NULL); slept -= tv.tv_usec/1e6+tv.tv_sec;	    if (progress->zero==0 || !nfirst++) continue;	    if ((current = progress->current) > outoff)	    {	delta = time (NULL) - progress->zero;		ratio = (double)(progress->final-outoff) /			(double)(current-outoff);		delta *= ratio - 1.0;		velocity=(current-lastcurrent)/(-slept*1024*1385);		fprintf (stdout,"%10lld/%lld (%4.1f%%) @%.1fx, "				"remaining %d:%02d\n",				current,progress->final,100.0/ratio,				velocity,delta/60,delta%60);		lastcurrent=current;	    }	    else		fprintf (stdout,"%10lld/%lld (%4.1f%%) @0x, remaining ??:??\n",				current,progress->final,0.0);	    fflush (stdout);	}	exit(0); /* not [normally] reached */    }    /* suck in first 64K and examine ISO9660 Primary Descriptor if present */    off = 0;    while ((n=read (infd,the_buffer+off,2*DVD_BLOCK-off)) > 0)    {	off += n;	if (off == 2*DVD_BLOCK)	{   if (!memcmp(the_buffer+DVD_BLOCK,"\1CD001",6))	    { struct iso_primary_descriptor *descr;		descr=(struct iso_primary_descriptor *)(the_buffer+DVD_BLOCK);		if (!zero_image)	        {   if (tracksize==0)		    {	tracksize=from_733(descr->volume_space_size)*CD_BLOCK;			if (capacity && (outoff+tracksize) > capacity)		    	{   fprintf (stderr,":-( %s: %lld blocks are free, "					    "%lld to be written\n",					    ioctl_device,					    (capacity-outoff)/2048,					    tracksize/2048);			    if (overburn)				fprintf (stderr,":-! ignoring...\n");			    else			    {	n = -1; errno = FATAL_START(ENOSPC);				goto out;			    }			}		    }		    /* else already checked for overburn condition */		    /* layer_break is meaningful only for -Z recording */		    if (layer_break>0 && !outoff)		    {	if (tracksize > layer_break*CD_BLOCK*2)			{   fprintf (stderr,":-( insane Layer Break position "					    "with respect to dataset size\n");			    n = -1; errno = FATAL_START(EINVAL);			    goto out;			}			if (!progress->final) progress->final = tracksize;			tracksize = layer_break*CD_BLOCK*2;		    }		}		else if (capacity > outoff)		{ int i=0;		  unsigned int ts = (tracksize=capacity-outoff)/2048;		    while (i<16 && descr->type[0] != (unsigned char)255)			to_733 (descr->volume_space_size,ts),			descr++, i++;		}		else		{   fprintf (stderr,":-( capacity is undefined or insane?\n");		    n = -1; errno = FATAL_START(EINVAL);/* ... or whatever */		    goto out;		}	    }	    else if (outoff && zero_image)	    {	fprintf (stderr,":-( no volume descriptors found "				"in previous session?\n");		n = -1; errno = FATAL_START(ENOTDIR);	/* ... or whatever */		goto out;	    }	    if (dry_run) close(infd), close(outfd), exit(0);	    if (poor_man)		/*		 * See commentary section in growisofs_mmc.cpp for		 * further details on poor_mans_setup		 */		pwrite64_method = poor_mans_setup (ioctl_handle,						   outoff+tracksize);	    if (!progress->final)	    {	if (tracksize)	progress->final = outoff+tracksize;		else		progress->final = capacity;	    }	    if (capacity && progress->final>capacity)		progress->final = capacity;	    progress->zero=time(NULL);	    /* Write two 32KB chunks, not one 64KB... */	    if ((n=(*pwrite64_method) (outfd,the_buffer,DVD_BLOCK,outoff))			!= DVD_BLOCK)	    {	if (n>0)	errno = FATAL_START(EIO);		else if (n==0)	errno = FATAL_START(ENOSPC);		n = -1;		goto out;	    }	    outoff += DVD_BLOCK;	    progress->current=outoff;	    if ((n=(*pwrite64_method) (outfd,the_buffer+DVD_BLOCK,DVD_BLOCK,outoff))			!= DVD_BLOCK)	    {	if (n>0)	errno = EIO;		else if (n==0)	errno = ENOSPC;		n = -1;		goto out;	    }	    outoff += DVD_BLOCK;	    progress->current=outoff;	    break;	}    }    if (n<=0) goto out;    /* yeah, really kludgy, shuffling file descriptor like that... */    if (zero_image)	close(infd), infd=open64 ("/dev/zero",O_RDONLY);    off = 0;    /*     * From now on only the first 32K of the_buffer are used!     */    while ((n=read (infd,the_buffer+off,DVD_BLOCK-off)) > 0)    {	off += n;	if (off == DVD_BLOCK)	{   off = 0;	    if ((n=(*pwrite64_method) (outfd,the_buffer,DVD_BLOCK,outoff))			!= DVD_BLOCK)	    {	if (n>0)	errno = EIO;		else if (n==0)	errno = ENOSPC;		n = -1;		break;	    }	    outoff += DVD_BLOCK;	    progress->current=outoff;	}    }    if (off)	/* pad to the closest 32K is needed */    {	memset (the_buffer+off,0,DVD_BLOCK-off);	if ((n=(*pwrite64_method) (outfd,the_buffer,DVD_BLOCK,outoff))			!= DVD_BLOCK)	{    if (n>0)		errno = EIO;	     else if (n==0)	errno = ENOSPC;	     n = -1;	}	outoff += DVD_BLOCK;    }    printf ("builtin_dd: %lld*2KB out @ average %.1fx1385KBps\n",	    (outoff-startoff)/2048,	    ((outoff-startoff)/(1024.0*1385.0))/(time(NULL)-progress->zero));out:    { int saved_errno=errno;	if (dry_run)	    close(infd), close(outfd), exit(errno);	if (pid!=(pid_t)-1) kill (pid,SIGTERM), waitpid (pid,NULL,0);	errno = outoff ? saved_errno : (n--?saved_errno:FATAL_START(EIO));    }  return n;}void pipe_mkisofs_up (char *mkisofs_argv[],int infd,int outfd,off64_t outoff){ pid_t mkisofs_pid;  int   fildes[2],ret,n;    if (pipe (fildes) < 0)        perror (":-( unable to create pipe"), exit(FATAL_START(errno));    if ((mkisofs_pid=fork ()) == (pid_t)-1)	perror (":-( unable to fork mkisofs"), exit(FATAL_START(errno));    else if (mkisofs_pid == 0)    {	dup2  (fildes[1],1);	close (fildes[0]);	close (fildes[1]);	close (outfd);	/* redundant:-) */#ifdef PASS_STDIN_TO_MKISOFS	dup2(infd,0);	close(infd);	infd=0;#endif	if ((n=fcntl (infd,F_GETFD))<0) n=0;	fcntl (infd,F_SETFD,n&~FD_CLOEXEC);	/*	 * If platform-specific setup_fds did not drop privileges,	 * do it now. I ignore return value because if it fails,	 * then privileges were dropped already.	 */	setuid(getuid());	execvp (mkisofs_argv[0],mkisofs_argv);	fprintf (stderr,":-( unable to execute %s: ",mkisofs_argv[0]),	perror (NULL), exit (FATAL_START(errno));    }    close (fildes[1]);    n=builtin_dd(fildes[0],outfd,outoff);    if (n==0) /* mkisofs must have finished, consume the exit code */

⌨️ 快捷键说明

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