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

📄 cdrwtool.c

📁 udf文件系统工具软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * cdrwtool - perform all sort of actions on a CD-R, CD-RW, and DVD-R drive. * * Copyright (c) 1999,2000	Jens Axboe <axboe@suse.de> * Copyright (c) 2002           Ben Fennema <bfennema@falcon.csc.calpoly.edu> * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <getopt.h>#include <signal.h>#include <sys/ioctl.h>#include <asm/param.h>#include <linux/cdrom.h>#include "cdrwtool.h"#include "../mkudffs/mkudffs.h"static int progress;int msf_to_lba(int m, int s, int f){	return (((m * 60) + s) * 75) + f;}void hexdump(const void *buffer, int size){	unsigned char *ptr = (unsigned char *) buffer;	int i;	for (i = 0; i < size; i++)		printf("%02x ", ptr[i]);	printf("\n");}void dump_sense(unsigned char *cdb, struct request_sense *sense){	int i;	printf("Command failed: ");	for (i=0; i<12; i++)		printf("%02x ", cdb[i]);	if (sense) {		printf("- sense %02x.%02x.%02x\n", sense->sense_key, sense->asc,						sense->ascq);	} else {		printf(", no sense\n");	}}int wait_cmd(int fd, struct cdrom_generic_command *cgc, unsigned char *buf,			 int dir, int timeout){	struct request_sense sense;	int ret;	if (cgc->timeout <= 0)		cgc->timeout = 500;	memset(&sense, 0, sizeof(sense));	cgc->buffer = buf;	cgc->data_direction = dir;	cgc->sense = &sense;	cgc->timeout = timeout;	ret = ioctl(fd, CDROM_SEND_PACKET, cgc);	if (ret)	{		perror("wait_cmd");		dump_sense(cgc->cmd, cgc->sense);	}	return ret;}int sigfd;void sig_progress(int sig){	struct cdrom_generic_command cgc;	struct request_sense sense;	static int did = 0;	int ret;	memset(&cgc, 0, sizeof(cgc));	memset(&sense, 0, sizeof(sense));	cgc.sense = &sense;	ret = wait_cmd(sigfd, &cgc, NULL, CGC_DATA_NONE, WAIT_PC);	if (!(sense.sks[0] & 0x80) && !did) {		printf("Progress indicator not implemented on this drive\n");		printf("Don't access drive until operation has completed\n");		progress = 101;		return;	}	progress = ((sense.sks[1] << 8 | sense.sks[2]) * 100) / 0xffff;	did = 1;	printf("%02d%% complete\n", progress);	if (progress == 99) {		progress = 101;		return;	}	alarm(2);}void print_completion_info(int fd){	sigfd = fd;	/* we can only poll sense for non-blocking commands */#if USE_IMMED == 0	return;#else	progress = 0;	signal(SIGALRM, sig_progress);	alarm(5);	while (progress < 100)		sleep(1);#endif}/* buffer must already have been filled by mode_sense */int mode_select(int fd, unsigned char *buffer, int len){	struct cdrom_generic_command cgc;	memset(&cgc, 0, sizeof(cgc));	memset(buffer, 0, 3);	cgc.cmd[0] = GPCMD_MODE_SELECT_10;	cgc.cmd[1] = 1 << 4;	cgc.cmd[8] = cgc.buflen = len;	return wait_cmd(fd, &cgc, buffer, CGC_DATA_WRITE, WAIT_PC);}int mode_sense(int fd, unsigned char *buffer, int page, char pc, int size){	struct cdrom_generic_command cgc;	memset(&cgc, 0, sizeof(cgc));	cgc.cmd[0] = GPCMD_MODE_SENSE_10;//	cgc.cmd[1] = 1 << 4;	cgc.cmd[2] = page | pc << 6;	cgc.cmd[8] = cgc.buflen = size;	return wait_cmd(fd, &cgc, buffer, CGC_DATA_READ, WAIT_PC);}int set_write_mode(int fd, write_params_t *w){	unsigned char header[0x10];	unsigned char *buffer;	int ret, len, offset;	memset(header, 0x00, sizeof(header));	len = 0x10;	if ((ret = mode_sense(fd, header, GPMODE_WRITE_PARMS_PAGE,			      PAGE_DEFAULT, len)) < 0)	{		perror("mode_sense_write");		return ret;	}	len = 2 + (((header[0] & 0xff) << 8) | (header[1] & 0xff));	offset = 8 + (((header[6] & 0xff) << 8) | (header[7] & 0xff));	buffer = calloc(len, sizeof(unsigned char));	if ((ret = mode_sense(fd, buffer, GPMODE_WRITE_PARMS_PAGE,			      PAGE_DEFAULT, len)) < 0)	{		perror("mode_sense_write");		return ret;	}	buffer[offset+2] = w->ls_v << 5;	buffer[offset+3] = w->track_mode | w->fpacket << 5 | w->border << 6;	buffer[offset+4] = w->data_block & 0xf;	buffer[offset+5] = w->link_size;	buffer[offset+8] = w->session_format & 0xff;	buffer[offset+10] = (w->packet_size >> 24) & 0xff;	buffer[offset+11] = (w->packet_size >> 16) & 0xff;	buffer[offset+12] = (w->packet_size >>  8) & 0xff;	buffer[offset+13] = w->packet_size & 0xff;	/* sub-header is only a mode-2 thing */	if (w->data_block == 10)	{		buffer[offset+48] = 0x00;		buffer[offset+49] = 0x00;		buffer[offset+50] = 0x08;		buffer[offset+51] = 0x00;	}	if ((ret = mode_select(fd, buffer, len)) < 0) {		hexdump(buffer, len);		free(buffer);		perror("mode_select");		return ret;	}	free(buffer);	return 0;}	int get_write_mode(int fd, write_params_t *w){	unsigned char header[0x10];	unsigned char *buffer;	int ret, len, offset;	memset(header, 0x00, sizeof(header));	len = 0x10;	if ((ret = mode_sense(fd, header, GPMODE_WRITE_PARMS_PAGE,			      PAGE_CURRENT, len)) < 0)	{		perror("mode_sense_write");		return ret;	}	len = 2 + (((header[0] & 0xff) << 8) | (header[1] & 0xff));	offset = 8 + (((header[6] & 0xff) << 8) | (header[7] & 0xff));	buffer = calloc(len, sizeof(unsigned char));	if ((ret = mode_sense(fd, buffer, GPMODE_WRITE_PARMS_PAGE,			      PAGE_CURRENT, len)) < 0)	{		perror("mode_sense_write");		return ret;	}	w->ls_v = (buffer[offset+2] >> 5) & 1;	w->border = (buffer[offset+3] >> 6) & 3;	w->fpacket = (buffer[offset+3] >> 5) & 1;	w->track_mode = buffer[offset+3] & 0xf;	w->data_block = buffer[offset+4] & 0xf;	w->link_size = buffer[offset+5];	w->session_format = buffer[offset+8];	w->packet_size = buffer[offset+13];	free(buffer);	return 0;}int sync_cache(int fd){	struct cdrom_generic_command cgc;	memset(&cgc, 0, sizeof(cgc));	cgc.cmd[0] = 0x35;	cgc.cmd[1] = 2;	return wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_SYNC);}int write_blocks(int fd, char *buffer, int lba, int blocks){	struct cdrom_generic_command cgc;	memset(&cgc, 0, sizeof(cgc));	cgc.cmd[0] = GPCMD_WRITE_10;#if 0	cgc.cmd[1] = 1 << 3;#endif	cgc.cmd[2] = (lba >> 24) & 0xff;	cgc.cmd[3] = (lba >> 16) & 0xff;	cgc.cmd[4] = (lba >>  8) & 0xff;	cgc.cmd[5] = lba & 0xff;	cgc.cmd[7] = (blocks >> 8) & 0xff;	cgc.cmd[8] = blocks & 0xff;	cgc.buflen = blocks * CDROM_BLOCK;	return wait_cmd(fd, &cgc, buffer, CGC_DATA_WRITE, WAIT_SYNC);}int write_file(int fd, struct cdrw_disc *disc){	int file, lba, size, blocks;	char *buf = NULL;	int ret = 0, go_on = 1;	if ((file = open(disc->filename, O_RDONLY)) < 0) {		fprintf(stderr, "can't open %s\n", disc->filename);		return 1;	}	/* for fixed packets, the write size is set. variable packets,	 * we write a little less than the buffer capacity. the drive	 * probably uses some of this for internal housekeeping, and	 * we want to completely eliminate buffer underruns.	 */	size = disc->fpacket ? disc->packet_size * CDROM_BLOCK : 63 * CDROM_BLOCK;	lba = disc->offset;	buf = (char *) malloc(size+1);	if (buf == NULL)		return 1;	while (!ret && go_on) {		blocks = disc->fpacket ? disc->packet_size : size / CDROM_BLOCK;		ret = read(file, buf, size);		if (ret == -1) {			perror("read from file");			break;		} else if (ret < size) {			/* not enough data to complete the packet. fill			 * the rest of the data block with zeros. we must			 * write out complete packets every time with			 * fixed packets. for variable packets we just			 * write what we have left.			 */			if (disc->fpacket) {				memset(&buf[ret], 0, size - ret - 1);			} else {				blocks = (ret + CDROM_BLOCK - 1) / CDROM_BLOCK;			}			/* regardless of type, this is the last write */			go_on = 0;		}		fprintf(stdout, "writing at lba = %d, blocks = %d\n", lba, blocks);		if ((ret = write_blocks(fd, buf, lba, blocks)))			break;		/* sync to indicate that one packet has been sent *///		sync_cache(fd);		/* for fixed packets, the run-in/run-out blocks are		 * contained within the packet size. variable packets		 * don't count them as part of the written size.		 */		lba += blocks;//		lba += disc->fpacket ? 0 : 7;	}	sync_cache(fd);	close(file);	free(buf);	return ret;}int blank_disc(int fd, int type){	struct cdrom_generic_command cgc;	int ret;	memset(&cgc, 0, sizeof(cgc));	cgc.cmd[0] = GPCMD_BLANK;	cgc.cmd[1] = (type == BLANK_FULL ? 0 : 1);

⌨️ 快捷键说明

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