示例#1
0
/*
 * will get the mode page only i.e. will strip off the header.
 */
int
get_mode_page(int fd, int page_no, int pc, int buf_len, uchar_t *buffer)
{
	int ret;
	uchar_t byte2, *buf;
	uint_t header_len, page_len, copy_cnt;

	byte2 = (uchar_t)(((pc << 6) & 0xC0) | (page_no & 0x3f));
	buf = (uchar_t *)my_zalloc(256);

	/* Ask 254 bytes only to make our IDE driver happy */
	ret = mode_sense(fd, byte2, 1, 254, buf);
	if (ret == 0) {
		free(buf);
		return (0);
	}

	header_len = 8 + read_scsi16(&buf[6]);
	page_len = buf[header_len + 1] + 2;

	copy_cnt = (page_len > buf_len) ? buf_len : page_len;
	(void) memcpy(buffer, &buf[header_len], copy_cnt);
	free(buf);

	return (1);
}
示例#2
0
文件: bstream.c 项目: andreiw/polaris
bstreamhandle
open_file_read_stream(char *file)
{
	bstreamhandle h;
	int fd;
	struct stat st;

	str_errno = 0;
	if (stat(file, &st) < 0)
		return (NULL);
	if ((st.st_mode & S_IFMT) == S_IFDIR) {
		str_errno = STR_ERR_NO_REG_FILE;
		return (NULL);
	}
	fd = open(file, O_RDONLY);
	if (fd < 0)
		return (NULL);
	h = (bstreamhandle)my_zalloc(sizeof (*h));
	h->bstr_fd = fd;
	h->bstr_read = file_stream_read;
	h->bstr_close = file_stream_close;
	h->bstr_size = file_stream_size;
	h->bstr_rewind = file_stream_rewind;

	return (h);
}
示例#3
0
/*
 * Find out media capacity.
 */
uint32_t
get_last_possible_lba(cd_device *dev)
{
	uchar_t *di;
	uint32_t cap;

	di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
	if (!read_disc_info(dev->d_fd, di)) {
		free(di);
		return (0);
	}

	/*
	 * If we have a DVD+R this field is an LBA. If the media is
	 * a CD-R/W the field is MSF formatted. Otherwise this field
	 * is not valid and will be zero.
	 */
	if (device_type == DVD_PLUS) {
		if (read_scsi32(&di[20]) != 0xffffffff) {
			cap = read_scsi32(&di[20]);
		} else {
			cap = 0;
		}
	} else {
		if ((di[21] != 0) && (di[21] != 0xff)) {
			cap = MSF2LBA(di[21], di[22], di[23]);
		} else {
			cap = 0;
		}
	}

	free(di);
	return (cap);
}
示例#4
0
文件: bstream.c 项目: andreiw/polaris
bstreamhandle
open_stdin_read_stream(void)
{
	bstreamhandle h;
	int mode;

	str_errno = 0;
	if ((mode = fcntl(0, F_GETFD, NULL)) < 0) {
		str_errno = STR_ERR_NO_READ_STDIN;
		return (NULL);
	}
	mode &= 3;
	if ((mode != O_RDONLY) && (mode != O_RDWR)) {
		str_errno = STR_ERR_NO_READ_STDIN;
		return (NULL);
	}
	h = (bstreamhandle)my_zalloc(sizeof (*h));
	h->bstr_fd = 0;
	h->bstr_read = file_stream_read;
	h->bstr_close = stdin_stream_close;
	h->bstr_size = file_stream_size;
	h->bstr_rewind = stdin_stream_rewind;

	return (h);
}
示例#5
0
文件: bstream.c 项目: andreiw/polaris
char *
get_tmp_name(void)
{
	char *t;
	char *envptr;

	t = (char *)my_zalloc(PATH_MAX);

	/*
	 * generate temp directory path based on this order:
	 * user specified (-m option), temp env variable,
	 * and finally /tmp if nothing is found.
	 */

	if (alt_tmp_dir) {

		/* copy and leave room for temp filename */

		(void) strlcpy(t, alt_tmp_dir, PATH_MAX - 10);
	} else {
		envptr = getenv("TMPDIR");
		if (envptr != NULL) {
			(void) strlcpy(t, envptr, PATH_MAX - 10);
		} else {
			(void) strlcpy(t, "/tmp", 5);
		}
	}

	/*
	 * no need to check if path is valid. statvfs will catch
	 * it later and fail with a proper error message.
	 */

	return (t);
}
示例#6
0
文件: bstream.c 项目: andreiw/polaris
bstreamhandle
open_temp_file_stream(void)
{
	bstreamhandle h;
	char *t;
	int fd;

	str_errno = 0;

	t = (char *)get_tmp_name();

	if (strlcat(t, "/cdXXXXXX", PATH_MAX) >= PATH_MAX)
		return (NULL);

	fd = mkstemp(t);

	if (debug)
		(void) printf("temp is: %s length: %d\n", t, strlen(t));

	if (fd < 0)
		return (NULL);
	(void) unlink(t);

	h = (bstreamhandle)my_zalloc(sizeof (*h));
	h->bstr_fd = fd;
	h->bstr_read = file_stream_read;
	h->bstr_write = file_stream_write;
	h->bstr_close = file_stream_close;
	h->bstr_size = file_stream_size;
	h->bstr_rewind = file_stream_rewind;

	return (h);
}
示例#7
0
文件: bstream.c 项目: andreiw/polaris
bstreamhandle
open_wav_write_stream(char *fname)
{
	bstreamhandle h;
	int esav, fd;
	uchar_t head[] = PRE_DEF_WAV_HDR;

	str_errno = 0;
	fd = -1;
	fd = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
	if (fd < 0)
		goto open_wav_write_stream_failed;
	if (write(fd, head, PRE_DEF_WAV_HDR_LEN) != PRE_DEF_WAV_HDR_LEN) {
		goto open_wav_write_stream_failed;
	}
	h = (bstreamhandle)my_zalloc(sizeof (*h));
	h->bstr_fd = fd;
	h->bstr_write = file_stream_write;
	h->bstr_close = wav_write_stream_close;
	return (h);

open_wav_write_stream_failed:
	esav = errno;
	if (fd != -1)
		(void) close(fd);
	errno = esav;
	return (NULL);
}
示例#8
0
/*
 * Manage sending of SET STREAMING command using the specified
 * read_speed and write_speed.
 *
 * This function allocates and initializes a Performance
 * Descriptor, which is sent as part of the SET STREAMING
 * command.  The descriptor is deallocated before function
 * exit.
 */
static int
do_set_streaming(cd_device *dev, uint_t read_speed,
	uint_t write_speed)
{
	int ret;
	uchar_t *str;

	/* Allocate and initialize the Performance Descriptor */
	str = (uchar_t *)my_zalloc(SET_STREAM_DATA_LEN);

	/* Read Time (in milliseconds) */
	load_scsi32(&str[16], 1000);
	/* Write Time (in milliseconds) */
	load_scsi32(&str[24], 1000);

	/* Read Speed */
	load_scsi32(&str[12], (uint32_t)read_speed);
	/* Write Speed */
	load_scsi32(&str[20], (uint32_t)write_speed);

	/* issue SET STREAMING command */
	ret = set_streaming(dev->d_fd, str);
	free(str);

	return (ret);
}
示例#9
0
/*
 * will take care of adding mode header and any extra bytes at the end.
 */
int
set_mode_page(int fd, uchar_t *buffer)
{
	int ret;
	uchar_t *buf;
	uint_t total, p_len;

	p_len = buffer[1] + 2;
	total = p_len + 8;
	buf = (uchar_t *)my_zalloc(total);

	(void) memcpy(&buf[8], buffer, p_len);
	if (debug) {
		int i;

		(void) printf("MODE: [");
		for (i = 0; i < p_len; i++) {
			(void) printf("0x%02x ", (uchar_t)buffer[i]);
		}

		(void) printf("]\n");
	}
	ret = mode_select(fd, total, buf);
	free(buf);

	return (ret);
}
示例#10
0
uchar_t
get_data_mode(int fd, uint32_t lba)
{
	int ret;
	uchar_t *buf;
	uchar_t mode;

	buf = (uchar_t *)my_zalloc(8);
	ret = read_header(fd, lba, buf);
	if (ret == 0)
		mode = 0xff;
	else
		mode = buf[0];
	free(buf);
	return (mode);
}
示例#11
0
文件: bstream.c 项目: andreiw/polaris
bstreamhandle
open_file_write_stream(char *fname)
{
	bstreamhandle h;
	int fd;

	str_errno = 0;
	fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
	if (fd < 0)
		return (NULL);
	h = (bstreamhandle)my_zalloc(sizeof (*h));
	h->bstr_fd = fd;
	h->bstr_write = file_stream_write;
	h->bstr_close = file_stream_close;
	return (h);
}
示例#12
0
/*
 * Find out media capacity.
 */
int
get_last_possible_lba(cd_device *dev)
{
	uchar_t *di;
	int cap;

	di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
	if (!read_disc_info(dev->d_fd, di)) {
		free(di);
		return (0);
	}
	if ((di[21] != 0) && (di[21] != 0xff)) {
		cap = ((di[21] * 60) + di[22]) * 75;
	} else {
		cap = 0;
	}

	free(di);
	return (cap);
}
示例#13
0
/*
 * Get current Read or Write Speed from Mode Page 0x2a.
 *
 * Use the size of the Page to determine which Multimedia Command
 * set (MMC) is present.  Based on the MMC version, get the
 * specified Read/Write Speed.
 *
 * Note that some MMC versions do not necessarily support a
 * (current) Read or Write Speed.  As a result, this function
 * _can_ return a value of zero.
 *
 * The newer standards (reserve and) mark the field(s) as Obsolete,
 * yet many vendors populate the Obsolete fields with valid values
 * (assumedly for backward compatibility).  This is important, as
 * a command like GET PERFORMANCE cannot return _the_ speed; it can
 * only return a Logical-Block-Address-dependent (LBA) speed.  Such
 * values can vary widely between the innermost and outermost Track.
 * Mode Page 0x2a is the best solution identifying "the current
 * (nominal) speed".
 */
static uint16_t
cd_speed_get(cd_device *dev, int cmd)
{
	uchar_t		*mp2a;
	uint16_t	rate = 0;
	int		offset;
	uint_t		buflen = 254;

	/*
	 * Allocate a buffer acceptably larger than any nominal
	 * Page for Page Code 0x2A.
	 */
	mp2a = (uchar_t *)my_zalloc(buflen);
	if (get_mode_page(dev->d_fd, 0x2A, 0, buflen, mp2a) == 0)
		goto end;

	/* Determine MMC version based on 'Page Length' field */
	switch (mp2a[1]) {
	case 0x14:  /* MMC-1 */
		if (debug)
			(void) printf("Mode Page 2A: MMC-1\n");

		offset = (cmd == GET_READ_SPEED) ? 14 : 20;
		rate = read_scsi16(&mp2a[offset]);
		break;


	case 0x18: /* MMC-2 */
		if (debug)
			(void) printf("Mode Page 2A: MMC-2;"
			    " Read and Write Speeds are "
			    "obsolete\n");

		/* see if "Obsolete" values are valid: */
		offset = (cmd == GET_READ_SPEED) ? 14 : 20;
		rate = read_scsi16(&mp2a[offset]);
		break;

	default: /* MMC-3 or newer */
		if (debug)
			(void) printf("Mode Page 2A: MMC-3 or"
			    " newer; Read Speed is obsolete.\n");

		if (cmd == GET_READ_SPEED) {
			/* this is Obsolete, but try it */
			offset = 14;
			rate = read_scsi16(&mp2a[offset]);
		} else {
			/* Write Speed is not obsolete */
			offset = 28;
			rate = read_scsi16(&mp2a[offset]);

			if (rate == 0) {
				/*
				 * then try an Obsolete field
				 * (but this shouldn't happen!)
				 */
				offset = 20;
				rate = read_scsi16(&mp2a[offset]);
			}
		}
		break;
	}
end:
	free(mp2a);

	if (debug)
		(void) printf("cd_speed_get: %s Speed is "
		    "%uX\n", (cmd == GET_READ_SPEED) ?
		    "Read" : "Write", cdrw_bandwidth_to_x(rate));
	return (rate);
}
示例#14
0
/*
 * Close session. This will write TOC.
 */
int
finalize(cd_device *dev)
{
	uchar_t *di;
	int count, ret, err;
	int immediate;
	int finalize_max;

	/*
	 * For ATAPI devices we will use the immediate mode and will
	 * poll the command for completion so that this command may
	 * not hog the channel. But for SCSI, we will use the treditional
	 * way of issuing the command with a large enough timeout. This
	 * is done because immediate mode was designed for ATAPI and some
	 * SCSI RW drives might not be even tested with it.
	 */
	if ((dev->d_inq[2] & 7) != 0) {
		/* SCSI device */
		immediate = 0;
	} else {
		/* non-SCSI (e.g ATAPI) device */
		immediate = 1;
	}

	/* We need to close track before close session */
	if (device_type == DVD_PLUS) {
		if (!close_track(dev->d_fd, 0, 0, immediate))
			return (0);
	}

	if (!close_track(dev->d_fd, 0, 1, immediate)) {
		/*
		 * For DAO mode which we use for DVD-RW, the latest MMC
		 * specification does not mention close_track. Some
		 * newer drives will return an ILLEGAL INSTRUCTION
		 * which we will ignore. We have also found a Panasonic
		 * drive which will return a MEDIA ERROR. It is safe
		 * to ignore both errors as this is not needed for
		 * these drives.
		 * This is kept for older drives which had needed
		 * us to issue close_track to flush the cache fully.
		 * once we are certain these drives have cleared the
		 * market, this can be removed.
		 */
		if (device_type == DVD_MINUS) {
			return (0);
		}
	} else {
		if (!immediate)
			return (1);
	}
	if (immediate) {
		(void) sleep(10);

		di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
		err = 0;

		if (device_type == CD_RW) {
			/* Finalization should not take more than 6 minutes */
			finalize_max = FINALIZE_TIMEOUT;
		} else {
			/* some DVD-RW drives take longer than 6 minutes */
			finalize_max = FINALIZE_TIMEOUT*2;
		}

		for (count = 0; count < finalize_max; count++) {
			ret = read_disc_info(dev->d_fd, di);
			if (ret != 0)
				break;
			if (uscsi_status != 2)
				err = 1;
			if (SENSE_KEY(rqbuf) == 2) {
				/* not ready but not becoming ready */
				if (ASC(rqbuf) != 4)
					err = 1;
			} else if (SENSE_KEY(rqbuf) == 5) {
				/* illegal mode for this track */
				if (ASC(rqbuf) != 0x64)
					err = 1;
			} else {
				err = 1;
			}
			if (err == 1) {
				if (debug) {
					(void) printf("Finalization failed\n");
					(void) printf("%x %x %x %x\n",
					    uscsi_status, SENSE_KEY(rqbuf),
					    ASC(rqbuf), ASCQ(rqbuf));
				}
				free(di);
				return (0);
			}
			if (uscsi_status == 2) {
				int i;
				/* illegal field in command packet */
				if (ASC(rqbuf) == 0x24) {
					/* print it out! */
					(void) printf("\n");
					for (i = 0; i < 18; i++)
						(void) printf("%x ",
						    (unsigned)(rqbuf[i]));
					(void) printf("\n");
				}
			}
			(void) sleep(5);
		}
		free(di);
	}
	return (ret);
}
示例#15
0
/*
 * Set page code 5 for TAO mode.
 */
int
prepare_for_write(cd_device *dev, int track_mode, int test_write,
    int keep_disc_open)
{
	uchar_t *buf;
	int no_err;
	int reset_device;

	if ((write_mode == DAO_MODE) && keep_disc_open) {
		(void) printf(gettext(
		    "Multi-session is not supported on DVD media\n"));
		exit(1);
	}

	if ((write_mode == DAO_MODE) && debug) {
		(void) printf("Preparing to write in DAO\n");
	}

	(void) start_stop(dev->d_fd, 1);
	/* Some drives do not support this command but still do it */
	(void) rezero_unit(dev->d_fd);

	buf = (uchar_t *)my_zalloc(64);

	no_err = get_mode_page(dev->d_fd, 5, 0, 64, buf);
	if (no_err)
		no_err = ((buf[1] + 2) > 64) ? 0 : 1;
	/*
	 * If the device is already in simulation mode and again a
	 * simulation is requested, then set the device in non-simulation
	 * 1st and then take it to simulation mode. This will flush any
	 * previous fake state in the drive.
	 */
	if (no_err && test_write && (buf[2] & 0x10)) {
		reset_device = 1;
	} else {
		reset_device = 0;
	}
	if (no_err != 0) {
		buf[0] &= 0x3f;

		/* set TAO or DAO writing mode */
		buf[2] = (write_mode == TAO_MODE)?1:2;

		/* set simulation flag */
		if (test_write && (!reset_device)) {
			buf[2] |= 0x10;
		} else {
			buf[2] &= ~0x10;
		}

		/* Turn on HW buffer underrun protection (BUFE) */
		if (!test_write) {
			buf[2] |= 0x40;
		}

		/* set track mode type */
		if (device_type == CD_RW) {
			buf[3] = track_mode & 0x0f;	/* ctrl nibble */
		} else {
			buf[3] = 5;	/* always 5 for DVD */
		}

		if (keep_disc_open) {
			buf[3] |= 0xc0;		/* Allow more sessions */
		}

		/* Select track type (audio or data) */
		if (track_mode == TRACK_MODE_DATA) {
			buf[4] = 8;		/* 2048 byte sector */
		} else {
			buf[4] = 0;		/* 2352 byte sector */
		}
		buf[7] = buf[8] = 0;

		/* Need to clear these fields for setting into DAO */
		if (write_mode == DAO_MODE)
			buf[5] = buf[15] = 0;

		/* print out mode for detailed log */
		if (debug && verbose) {
			int i;

			(void) printf("setting = [ ");
			for (i = 0; i < 15; i++)
				(void) printf("0x%x ", buf[i]);
			(void) printf("]\n");
		}

		no_err = set_mode_page(dev->d_fd, buf);

		if (no_err && reset_device) {
			/* Turn the test write bit back on */
			buf[2] |= 0x10;
			no_err = set_mode_page(dev->d_fd, buf);
		}

		/*
		 * Since BUFE is the only optional flag we are
		 * setting we will try to turn it off if the command
		 * fails.
		 */
		if (!no_err) {
			/*
			 * Some old drives may not support HW
			 * buffer underrun protection, try again
			 * after turning it off.
			 */
			if (debug)
				(void) printf("Turning off BUFE\n");
			buf[2] &= ~0x40;
			no_err = set_mode_page(dev->d_fd, buf);
		}
	}

	free(buf);
	return (no_err);
}
示例#16
0
/*
 * Builds track information database for track trackno. If trackno is
 * -1, builds the database for next blank track.
 */
int
build_track_info(cd_device *dev, int trackno, struct track_info *t_info)
{
	uchar_t *ti;
	uchar_t toc[20];		/* 2 entries + 4 byte header */
	int ret;

	(void) memset(t_info, 0, sizeof (*t_info));
	/* 1st try READ TRACK INFORMATION */
	ti = (uchar_t *)my_zalloc(TRACK_INFO_SIZE);
	t_info->ti_track_no = trackno;

	/* Gererate faked information for writing to DVD */
	if (device_type != CD_RW) {
		uint_t bsize;

		t_info->ti_flags = 0x3000;
		t_info->ti_track_no = 1;
		t_info->ti_session_no = 1;
		t_info->ti_track_mode = 0x4;
		t_info->ti_data_mode = 1;
		t_info->ti_start_address = 0;

		/* only 1 track on DVD make it max size */
		t_info->ti_track_size = read_format_capacity(target->d_fd,
		    &bsize);
		if (t_info->ti_track_size < MAX_CD_BLKS) {
			t_info->ti_track_size = MAX_DVD_BLKS;
		}

		t_info->ti_nwa = 0;
		t_info->ti_lra = 0;
		t_info->ti_packet_size = 0x10;
		t_info->ti_free_blocks = 0;
	}

	if (read_track_info(dev->d_fd, trackno, ti)) {

		if (debug)
			(void) printf("using read_track_info for TOC \n");

		t_info->ti_track_no = ti[2];
		t_info->ti_session_no = ti[3];
		t_info->ti_flags = (ti[6] >> 4) & 0xf;
		t_info->ti_flags |= (uint32_t)(ti[5] & 0xf0);
		t_info->ti_flags |= (uint32_t)(ti[7]) << 8;
		t_info->ti_flags |= TI_SESSION_NO_VALID | TI_FREE_BLOCKS_VALID;
		t_info->ti_track_mode = ti[5] & 0xf;
		if ((ti[6] & 0xf) == 0xf)
			t_info->ti_data_mode = 0xff;
		else
			t_info->ti_data_mode = ti[6] & 0xf;
		t_info->ti_start_address = read_scsi32(&ti[8]);
		t_info->ti_nwa = read_scsi32(&ti[12]);
		t_info->ti_free_blocks = read_scsi32(&ti[16]);
		t_info->ti_packet_size = read_scsi32(&ti[20]);
		t_info->ti_track_size = read_scsi32(&ti[24]);
		t_info->ti_lra = read_scsi32(&ti[28]);
		free(ti);
		return (1);
	}
	/* READ TRACK INFORMATION not supported, try other options */
	free(ti);
	/*
	 * We can get info for next blank track if READ TRACK INFO is not
	 * supported.
	 */
	if (trackno == -1)
		return (0);

	if (debug)
		(void) printf("using READ_TOC for TOC\n");

	/* Try Read TOC */
	if (!read_toc(dev->d_fd, 0, trackno, 20, toc)) {
		return (0);
	}
	t_info->ti_start_address = read_scsi32(&toc[8]);
	t_info->ti_track_mode = toc[5] & 0xf;
	t_info->ti_track_size = read_scsi32(&toc[16]) - read_scsi32(&toc[8]);
	t_info->ti_data_mode = get_data_mode(dev->d_fd, read_scsi32(&toc[8]));

	/* Numbers for audio tracks are always in 2K chunks */
	if ((dev->d_blksize == 512) && ((t_info->ti_track_mode & 4) == 0)) {
		t_info->ti_start_address /= 4;
		t_info->ti_track_size /= 4;
	}

	/* Now find out the session thing */
	ret = read_toc(dev->d_fd, 1, trackno, 12, toc);

	/*
	 * Make sure that the call succeeds and returns the requested
	 * TOC size correctly.
	 */

	if ((ret == 0) || (toc[1] != 0x0a)) {

		/* For ATAPI drives or old Toshiba drives */
		ret = read_toc_as_per_8020(dev->d_fd, 1, trackno, 12, toc);
	}
	/* If this goes through well TOC length will always be 0x0a */
	if (ret && (toc[1] == 0x0a)) {
		if (trackno >= toc[6]) {
			t_info->ti_session_no = toc[3];
			t_info->ti_flags |= TI_SESSION_NO_VALID;
		}
		/*
		 * This might be the last track of this session. If so,
		 * exclude the leadout and next lead in.
		 */
		if (trackno == (toc[6] - 1)) {
			/*
			 * 1.5 Min leadout + 1 min. leadin + 2 sec. pre-gap.
			 * For 2nd+ leadout it will be 0.5 min. But currently
			 * there is no direct way. And it will not happen
			 * for any normal case.
			 *
			 * 75 frames/sec, 60 sec/min, so leadin gap is
			 * ((1.5 +1)*60 + 2)*75 = 11400 frames (blocks)
			 */
			t_info->ti_track_size -= 11400;
		}
	}
	return (1);
}
示例#17
0
文件: bstream.c 项目: andreiw/polaris
bstreamhandle
open_wav_read_stream(char *fname)
{
	bstreamhandle h;
	int fd, sav;
	Wave_filehdr *wav;
	struct stat st;
	uint32_t data_size;

	wav = NULL;
	str_errno = 0;
	fd = open(fname, O_RDONLY);
	if (fd < 0)
		return (NULL);

	if (fstat(fd, &st) < 0) {
		goto wav_open_failed;
	}
	if ((st.st_mode & S_IFMT) != S_IFREG) {
		str_errno = STR_ERR_NO_REG_FILE;
		goto wav_open_failed;
	}
	wav = (Wave_filehdr *)my_zalloc(sizeof (*wav));
	if (read(fd, wav, sizeof (*wav)) != sizeof (*wav)) {
		str_errno = STR_ERR_WAV_READ_ERR;
		goto wav_open_failed;
	}
	if ((strncmp(wav->riff, "RIFF", 4) != 0) ||
		(strncmp(wav->wave, "WAVE", 4) != 0)) {
		str_errno = STR_ERR_WAV_BAD_HEADER;
		goto wav_open_failed;
	}
	if (((CPU_TO_LE32(wav->total_chunk_size) + 8) != st.st_size) ||
	    (strncmp(wav->fmt, "fmt ", 4) != 0) ||
	    (CPU_TO_LE16(wav->fmt_tag) != 1) ||
	    (CPU_TO_LE16(wav->n_channels) != 2) ||
	    (CPU_TO_LE32(wav->sample_rate) != 44100) ||
	    (CPU_TO_LE16(wav->bits_per_sample) != 16) ||
	    (strncmp(wav->data, "data", 4) != 0) ||
	    ((CPU_TO_LE32(wav->data_size) + 44) != st.st_size)) {

		str_errno = STR_ERR_WAV_UNSUPPORTED_FORMAT;
		goto wav_open_failed;
	}
	data_size = CPU_TO_LE32(wav->data_size);
	if (lseek(fd, sizeof (*wav), SEEK_SET) < 0) {
		goto wav_open_failed;
	}

	free(wav);
	h = (bstreamhandle)my_zalloc(sizeof (*h));
	h->bstr_fd = fd;
	h->bstr_read = file_stream_read;
	h->bstr_close = file_stream_close;
	h->bstr_size = audio_stream_size;
	h->bstr_rewind = wav_stream_rewind;
	h->bstr_private = (void *)data_size;

	return (h);

wav_open_failed:
	sav = errno;
	(void) close(fd);
	if (wav != NULL)
		free(wav);
	errno = sav;
	return (NULL);
}
示例#18
0
/*
 * The size of the last track in one of the first N - 1 sessions of an
 * N-session (N > 1) disc is reported incorrectly by some drives and calculated
 * incorrectly for others, because a pre-gap/lead-out/lead-in section that ends
 * a session is erroneously considered part of that track. This function checks
 * for this corner case, and adjusts the track size if necessary.
 */
static int
check_track_size(cd_device *dev, int trk_num, struct track_info *tip)
{
	size_t raw_toc_len;
	uchar_t *raw_toc;
	rtoc_hdr_t hdr;
	uint32_t sess_leadout_lba;
	int sess_last_trk_num;
	int trk_sess_num;
	uint32_t trk_size;

	/* Request Raw TOC Header for session count. */
	if (read_toc(dev->d_fd, FORMAT_RAW_TOC, 1,
	    sizeof (rtoc_hdr_t), (uchar_t *)&hdr) != 1)
		return (0);

	/* Is this a multi-session medium? */
	if (hdr.rh_last_sess_num > hdr.rh_first_sess_num) {
		/* Yes; request entire Raw TOC. */
		raw_toc_len = read_scsi16(&hdr.rh_data_len1) + RTOC_DATA_LEN_SZ;
		raw_toc = (uchar_t *)my_zalloc(raw_toc_len);

		if (read_toc(dev->d_fd, FORMAT_RAW_TOC, 1, raw_toc_len, raw_toc)
		    != 1)
			goto fail;

		if (rtoc_get_trk_sess_num(raw_toc, raw_toc_len, trk_num,
		    &trk_sess_num) != 1)
			goto fail;

		tip->ti_session_no = trk_sess_num;
		tip->ti_flags |= TI_SESSION_NO_VALID;

		/* Is the track in one of the first N - 1 sessions? */
		if (trk_sess_num < hdr.rh_last_sess_num) {
			if (rtoc_get_sess_last_trk_num(raw_toc, raw_toc_len,
			    trk_sess_num, &sess_last_trk_num) != 1)
				goto fail;

			/* Is the track the last track in the session? */
			if (trk_num == sess_last_trk_num) {
				if (rtoc_get_sess_leadout_lba(raw_toc,
				    raw_toc_len, trk_sess_num,
				    &sess_leadout_lba) != 1)
					goto fail;

				trk_size = sess_leadout_lba -
				    tip->ti_start_address;

				/* Fix track size if it was too big. */
				if (tip->ti_track_size > trk_size)
					tip->ti_track_size = trk_size;
			}
		}
		free(raw_toc);
	}
	return (1);

fail:
	free(raw_toc);
	return (0);
}
示例#19
0
void
info(void)
{
	uchar_t *toc, *p, *conf;
	int ret, toc_size;
	uint_t bsize;
	size_t cap = 0;
	char *msg;
	struct track_info *ti;

	msg = gettext("Cannot read Table of contents\n");

	get_media_type(target->d_fd);

	(void) printf(gettext("\nDevice : %.8s %.16s\n"),
	    &target->d_inq[8], &target->d_inq[16]);
	(void) printf(gettext("Firmware : Rev. %.4s (%.12s)\n"),
	    &target->d_inq[32], &target->d_inq[36]);

	if (check_device(target, CHECK_DEVICE_NOT_READY)) {
		(void) check_device(target, CHECK_NO_MEDIA |
		    EXIT_IF_CHECK_FAILED);
		(void) check_device(target, CHECK_DEVICE_NOT_READY |
		    EXIT_IF_CHECK_FAILED);
	}

	if (verbose != 0) {
		/*
		 * Determine the media type by reading the active profile
		 * from the profile list.
		 */
		(void) printf(gettext("Media Type : "));

		conf = (uchar_t *)my_zalloc(MMC_FTR_HDR_LEN);

		if (get_configuration(target->d_fd, MMC_FTR_PRFL_LIST,
		    MMC_FTR_HDR_LEN, conf))
			print_profile_name(read_scsi16(&conf[6]), 0, 1);
		else
			(void) printf(gettext("UNKNOWN\n"));

		free(conf);

		/*
		 * Get the start address of the last possible lead out.
		 */
		cap = get_last_possible_lba(target);

		/*
		 * The start address of the last possible leadout will only
		 * be zero if the disc is full or this drive does not support
		 * this method of determining capacity.
		 */
		if (cap == 0)
			cap = read_format_capacity(target->d_fd, &bsize);

		/*
		 * Since both methods of determining the capacity of the
		 * media count the correct number of blocks, just multiply
		 * the capacity by the block size.
		 */
		cap *= target->d_blksize;

		if (device_type == CD_RW) {
			(void) printf(gettext("Media Capacity : %.2f MB "),
			    ((double)cap/ONE_MB_BASE2));
		} else {
			/*
			 * For DVD's make sure we print out "Formatted Media
			 * Capacity". Don't do this for CD-RWs as only
			 * DVDs are formatted.
			 */
			(void) printf(gettext("Formatted Media Capacity : "
			    "%.2f GB "), ((double)cap/ONE_GB_BASE10));
		}

		cap /= target->d_blksize;
		(void) printf(gettext("(%u blocks)\n"), (uint_t)cap);
	}

	if (!check_device(target, CHECK_MEDIA_IS_NOT_BLANK)) {
		(void) printf(gettext("Media is blank\n"));
		exit(0);
	}

	/*  Find out the number of entries in the toc */
	toc = (uchar_t *)my_zalloc(12);
	if (!read_toc(target->d_fd, 0, 1, 4, toc)) {
		err_msg(msg);
	} else {
		toc_size = 256*toc[0] + toc[1] + 2;
		free(toc);

		/* allocate enough space for each track entry */
		toc = (uchar_t *)my_zalloc(toc_size);

		if (!read_toc(target->d_fd, 0, 1, toc_size, toc)) {
			err_msg(msg);
			exit(1);
		}
		(void) printf("\n");

		/* l10n_NOTE : Preserve column numbers of '|' character */
		(void) printf(gettext("Track No. |Type    |Start address\n"));
		(void) printf("----------+--------+-------------\n");


		/* look at each track and display it's type. */

		for (p = &toc[4]; p < (toc + toc_size); p += 8) {
			if (p[2] != 0xAA)
				(void) printf(" %-3d      |", p[2]);
			else
				(void) printf("Leadout   |");
			(void) printf("%s   |", (p[1] & 4) ? gettext("Data ") :
			    gettext("Audio"));
			(void) printf("%u\n", read_scsi32(&p[4]));
		}
	}
	(void) printf("\n");
	ret = read_toc(target->d_fd, 1, 0, 12, toc);
	if ((ret == 0) || (toc[1] != 0x0a))
		/* For ATAPI drives or old Toshiba drives */
		ret = read_toc_as_per_8020(target->d_fd, 1, 0, 12, toc);

	if (ret && (toc[1] == 0x0a)) {
		(void) printf(gettext("Last session start address: %u\n"),
		    read_scsi32(&toc[8]));
	}
	free(toc);
	ti = (struct track_info *)my_zalloc(sizeof (struct track_info));

	if (build_track_info(target, -1, ti) && (ti->ti_flags & TI_NWA_VALID)) {
		(void) printf(gettext("Next writable address: %u\n"),
		    ti->ti_nwa);
	}
	free(ti);
	exit(0);
}
示例#20
0
文件: bstream.c 项目: andreiw/polaris
bstreamhandle
open_au_read_stream(char *fname)
{
	bstreamhandle h;
	int fd, sav;
	au_filehdr_t *au;
	struct stat st;
	uint32_t data_size;

	au = NULL;
	str_errno = 0;
	fd = open(fname, O_RDONLY);
	if (fd < 0)
		return (NULL);

	if (fstat(fd, &st) < 0) {
		goto au_open_failed;
	}
	if ((st.st_mode & S_IFMT) != S_IFREG) {
		str_errno = STR_ERR_NO_REG_FILE;
		goto au_open_failed;
	}
	au = (au_filehdr_t *)my_zalloc(sizeof (*au));
	if (read(fd, au, sizeof (*au)) != sizeof (*au)) {
		str_errno = STR_ERR_AU_READ_ERR;
		goto au_open_failed;
	}
	au->au_magic = BE32_TO_CPU(au->au_magic);
	au->au_offset = BE32_TO_CPU(au->au_offset);
	au->au_data_size = BE32_TO_CPU(au->au_data_size);
	au->au_encoding = BE32_TO_CPU(au->au_encoding);
	au->au_sample_rate = BE32_TO_CPU(au->au_sample_rate);
	au->au_channels = BE32_TO_CPU(au->au_channels);

	if (au->au_magic != AUDIO_AU_FILE_MAGIC) {
		str_errno = STR_ERR_AU_BAD_HEADER;
		goto au_open_failed;
	}
	if ((au->au_encoding != AUDIO_AU_ENCODING_LINEAR_16) ||
	    (au->au_sample_rate != 44100) || (au->au_channels != 2)) {

		str_errno = STR_ERR_AU_UNSUPPORTED_FORMAT;
		goto au_open_failed;
	}
	if (au->au_data_size != AUDIO_AU_UNKNOWN_SIZE) {
		if ((au->au_offset + au->au_data_size) != st.st_size) {
			str_errno = STR_ERR_AU_BAD_HEADER;
			goto au_open_failed;
		}
		data_size = au->au_data_size;
	} else {
		data_size = st.st_size - au->au_offset;
	}
	if (data_size == 0) {
		str_errno = STR_ERR_AU_UNSUPPORTED_FORMAT;
		goto au_open_failed;
	}
	if (lseek(fd, au->au_offset, SEEK_SET) < 0) {
		goto au_open_failed;
	}

	free(au);
	h = (bstreamhandle)my_zalloc(sizeof (*h));
	h->bstr_fd = fd;
	h->bstr_read = file_stream_read_wrbo;
	h->bstr_close = file_stream_close;
	h->bstr_size = audio_stream_size;
	h->bstr_rewind = au_stream_rewind;
	h->bstr_private = (void *)data_size;

	return (h);

au_open_failed:
	sav = errno;
	(void) close(fd);
	if (au != NULL)
		free(au);
	errno = sav;
	return (NULL);
}