xref: /onnv-gate/usr/src/cmd/cdrw/bstream.c (revision 4274:b18a82c8bc06)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52523Szk194757  * Common Development and Distribution License (the "License").
62523Szk194757  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*4274Szk194757  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <fcntl.h>
290Sstevel@tonic-gate #include <string.h>
300Sstevel@tonic-gate #include <errno.h>
310Sstevel@tonic-gate #include <sys/types.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <sys/stat.h>
340Sstevel@tonic-gate #include <sys/statvfs.h>
350Sstevel@tonic-gate #include <stdio.h>
360Sstevel@tonic-gate #include <stdlib.h>
370Sstevel@tonic-gate #include <libintl.h>
380Sstevel@tonic-gate #include <limits.h>
390Sstevel@tonic-gate #include <audio/au.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #include "bstream.h"
420Sstevel@tonic-gate #include "util.h"
430Sstevel@tonic-gate #include "audio.h"
440Sstevel@tonic-gate #include "byteorder.h"
450Sstevel@tonic-gate #include "main.h"
460Sstevel@tonic-gate 
470Sstevel@tonic-gate int str_errno;
480Sstevel@tonic-gate 
490Sstevel@tonic-gate char *
str_errno_to_string(int serrno)500Sstevel@tonic-gate str_errno_to_string(int serrno)
510Sstevel@tonic-gate {
520Sstevel@tonic-gate 	switch (serrno) {
530Sstevel@tonic-gate 	case STR_ERR_NO_ERR:
540Sstevel@tonic-gate 		return (gettext("No error"));
550Sstevel@tonic-gate 	case STR_ERR_NO_REG_FILE:
560Sstevel@tonic-gate 		return (gettext("Not a regular file"));
570Sstevel@tonic-gate 	case STR_ERR_NO_READ_STDIN:
580Sstevel@tonic-gate 		return (gettext("Stdin not open for reading"));
590Sstevel@tonic-gate 	case STR_ERR_AU_READ_ERR:
600Sstevel@tonic-gate 		return (gettext("Unable to read au header"));
610Sstevel@tonic-gate 	case STR_ERR_AU_UNSUPPORTED_FORMAT:
620Sstevel@tonic-gate 		return (gettext("Unsupported au format"));
630Sstevel@tonic-gate 	case STR_ERR_AU_BAD_HEADER:
640Sstevel@tonic-gate 		return (gettext("Bad au header"));
650Sstevel@tonic-gate 	case STR_ERR_WAV_READ_ERR:
660Sstevel@tonic-gate 		return (gettext("Unable to read wav header"));
670Sstevel@tonic-gate 	case STR_ERR_WAV_UNSUPPORTED_FORMAT:
680Sstevel@tonic-gate 		return (gettext("Unsupported wav format"));
690Sstevel@tonic-gate 	case STR_ERR_WAV_BAD_HEADER:
700Sstevel@tonic-gate 		return (gettext("Bad wav header"));
71*4274Szk194757 	case STR_ERR_ISO_READ_ERR:
72*4274Szk194757 		return (gettext("Unable to read ISO header"));
73*4274Szk194757 	case STR_ERR_ISO_BAD_HEADER:
74*4274Szk194757 		return (gettext("Invalid ISO header or not an ISO"));
750Sstevel@tonic-gate 	default:
760Sstevel@tonic-gate 		return (gettext("unknown error"));
770Sstevel@tonic-gate 	}
780Sstevel@tonic-gate }
790Sstevel@tonic-gate 
800Sstevel@tonic-gate static int
file_stream_size(bstreamhandle h,off_t * size)810Sstevel@tonic-gate file_stream_size(bstreamhandle h, off_t *size)
820Sstevel@tonic-gate {
830Sstevel@tonic-gate 	struct stat st;
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 	str_errno = 0;
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	if (fstat(h->bstr_fd, &st) < 0)
880Sstevel@tonic-gate 		return (0);
890Sstevel@tonic-gate 	if ((st.st_mode & S_IFMT) != S_IFREG) {
900Sstevel@tonic-gate 		str_errno = STR_ERR_NO_REG_FILE;
910Sstevel@tonic-gate 		return (0);
920Sstevel@tonic-gate 	}
930Sstevel@tonic-gate 	*size = st.st_size;
940Sstevel@tonic-gate 	return (1);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate 
970Sstevel@tonic-gate static int
audio_stream_size(bstreamhandle h,off_t * size)980Sstevel@tonic-gate audio_stream_size(bstreamhandle h, off_t *size)
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate 	str_errno = 0;
1010Sstevel@tonic-gate 	*size = (off_t)(uintptr_t)(h->bstr_private);
1020Sstevel@tonic-gate 	return (1);
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate static int
file_stream_read(bstreamhandle h,uchar_t * buf,off_t size)1060Sstevel@tonic-gate file_stream_read(bstreamhandle h, uchar_t *buf, off_t size)
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate 	str_errno = 0;
1090Sstevel@tonic-gate 	return (read(h->bstr_fd, buf, size));
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate static int
file_stream_write(bstreamhandle h,uchar_t * buf,off_t size)1130Sstevel@tonic-gate file_stream_write(bstreamhandle h, uchar_t *buf, off_t size)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate 	str_errno = 0;
1160Sstevel@tonic-gate 	return (write(h->bstr_fd, buf, size));
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate /*
1200Sstevel@tonic-gate  * with reverse byteorder
1210Sstevel@tonic-gate  */
1220Sstevel@tonic-gate static int
file_stream_read_wrbo(bstreamhandle h,uchar_t * buf,off_t size)1230Sstevel@tonic-gate file_stream_read_wrbo(bstreamhandle h, uchar_t *buf, off_t size)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate 	int cnt;
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	str_errno = 0;
1280Sstevel@tonic-gate 	cnt = read(h->bstr_fd, buf, size);
1290Sstevel@tonic-gate 	if (cnt > 0) {
1300Sstevel@tonic-gate 		int i;
1310Sstevel@tonic-gate 		uchar_t ch;
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 		for (i = 0; i < cnt; i += 2) {
1340Sstevel@tonic-gate 			ch = buf[i];
1350Sstevel@tonic-gate 			buf[i] = buf[i+1];
1360Sstevel@tonic-gate 			buf[i+1] = ch;
1370Sstevel@tonic-gate 		}
1380Sstevel@tonic-gate 	}
1390Sstevel@tonic-gate 	return (cnt);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate  * This will change the byteorder in the buffer but that is fine with us.
1440Sstevel@tonic-gate  */
1450Sstevel@tonic-gate static int
file_stream_write_wrbo(bstreamhandle h,uchar_t * buf,off_t size)1460Sstevel@tonic-gate file_stream_write_wrbo(bstreamhandle h, uchar_t *buf, off_t size)
1470Sstevel@tonic-gate {
1480Sstevel@tonic-gate 	int i;
1490Sstevel@tonic-gate 	uchar_t ch;
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	str_errno = 0;
1520Sstevel@tonic-gate 	if (size > 0) {
1530Sstevel@tonic-gate 		for (i = 0; i < size; i += 2) {
1540Sstevel@tonic-gate 			ch = buf[i];
1550Sstevel@tonic-gate 			buf[i] = buf[i+1];
1560Sstevel@tonic-gate 			buf[i+1] = ch;
1570Sstevel@tonic-gate 		}
1580Sstevel@tonic-gate 	}
1590Sstevel@tonic-gate 	return (write(h->bstr_fd, buf, size));
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate static int
file_stream_close(bstreamhandle h)1630Sstevel@tonic-gate file_stream_close(bstreamhandle h)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate 	int fd;
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	str_errno = 0;
1680Sstevel@tonic-gate 	fd = h->bstr_fd;
1690Sstevel@tonic-gate 	free(h);
1700Sstevel@tonic-gate 	return (close(fd));
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate static int
stdin_stream_close(bstreamhandle h)1740Sstevel@tonic-gate stdin_stream_close(bstreamhandle h)
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate 	str_errno = 0;
1770Sstevel@tonic-gate 	free(h);
1780Sstevel@tonic-gate 	return (0);
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate static int
wav_write_stream_close(bstreamhandle h)1820Sstevel@tonic-gate wav_write_stream_close(bstreamhandle h)
1830Sstevel@tonic-gate {
1840Sstevel@tonic-gate 	uint32_t sz;
1850Sstevel@tonic-gate 	Wave_filehdr wav;
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	str_errno = 0;
1880Sstevel@tonic-gate 	(void) memset(&wav, 0, sizeof (wav));
1890Sstevel@tonic-gate 	sz = lseek(h->bstr_fd, 0L, SEEK_END);
1900Sstevel@tonic-gate 	(void) lseek(h->bstr_fd, 0L, SEEK_SET);
1910Sstevel@tonic-gate 	if (read(h->bstr_fd, &wav, sizeof (wav)) != sizeof (wav)) {
1920Sstevel@tonic-gate 		return (1);
1930Sstevel@tonic-gate 	}
1940Sstevel@tonic-gate 	wav.total_chunk_size = CPU_TO_LE32(sz - 8);
1950Sstevel@tonic-gate 	wav.data_size = CPU_TO_LE32(sz - 44);
1960Sstevel@tonic-gate 	(void) lseek(h->bstr_fd, 0L, SEEK_SET);
1970Sstevel@tonic-gate 	if (write(h->bstr_fd, &wav, sizeof (wav)) != sizeof (wav)) {
1980Sstevel@tonic-gate 		return (1);
1990Sstevel@tonic-gate 	}
2000Sstevel@tonic-gate 	(void) close(h->bstr_fd);
2010Sstevel@tonic-gate 	free(h);
2020Sstevel@tonic-gate 	return (0);
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate static int
au_write_stream_close(bstreamhandle h)2060Sstevel@tonic-gate au_write_stream_close(bstreamhandle h)
2070Sstevel@tonic-gate {
2080Sstevel@tonic-gate 	uint32_t sz;
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	str_errno = 0;
2110Sstevel@tonic-gate 	sz = lseek(h->bstr_fd, 0L, SEEK_END);
2120Sstevel@tonic-gate 	sz -= PRE_DEF_AU_HDR_LEN;
2130Sstevel@tonic-gate 	sz = CPU_TO_BE32(sz);
2140Sstevel@tonic-gate 	if (lseek(h->bstr_fd, 8L, SEEK_SET) < 0)
2150Sstevel@tonic-gate 		return (1);
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	if (write(h->bstr_fd, &sz, 4) < 0)
2180Sstevel@tonic-gate 		return (1);
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	(void) close(h->bstr_fd);
2210Sstevel@tonic-gate 	free(h);
2220Sstevel@tonic-gate 	return (0);
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate /* ARGSUSED */
2260Sstevel@tonic-gate static void
stdin_stream_rewind(bstreamhandle h)2270Sstevel@tonic-gate stdin_stream_rewind(bstreamhandle h)
2280Sstevel@tonic-gate {
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate static void
file_stream_rewind(bstreamhandle h)2320Sstevel@tonic-gate file_stream_rewind(bstreamhandle h)
2330Sstevel@tonic-gate {
2340Sstevel@tonic-gate 	(void) lseek(h->bstr_fd, 0L, SEEK_SET);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate static void
au_stream_rewind(bstreamhandle h)2380Sstevel@tonic-gate au_stream_rewind(bstreamhandle h)
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate 	au_filehdr_t au;
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	(void) lseek(h->bstr_fd, 0L, SEEK_SET);
2430Sstevel@tonic-gate 	if (read(h->bstr_fd, &au, sizeof (au)) != sizeof (au)) {
2440Sstevel@tonic-gate 		return;
2450Sstevel@tonic-gate 	}
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	if (lseek(h->bstr_fd, (long)(BE32_TO_CPU(au.au_offset)),
2480Sstevel@tonic-gate 	    SEEK_SET) < 0) {
2490Sstevel@tonic-gate 		return;
2500Sstevel@tonic-gate 	}
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate static void
wav_stream_rewind(bstreamhandle h)2540Sstevel@tonic-gate wav_stream_rewind(bstreamhandle h)
2550Sstevel@tonic-gate {
2560Sstevel@tonic-gate 	(void) lseek(h->bstr_fd, (long)(sizeof (Wave_filehdr)), SEEK_SET);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate bstreamhandle
open_file_read_stream(char * file)2600Sstevel@tonic-gate open_file_read_stream(char *file)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate 	bstreamhandle h;
2630Sstevel@tonic-gate 	int fd;
2640Sstevel@tonic-gate 	struct stat st;
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	str_errno = 0;
2670Sstevel@tonic-gate 	if (stat(file, &st) < 0)
2680Sstevel@tonic-gate 		return (NULL);
2690Sstevel@tonic-gate 	if ((st.st_mode & S_IFMT) == S_IFDIR) {
2700Sstevel@tonic-gate 		str_errno = STR_ERR_NO_REG_FILE;
2710Sstevel@tonic-gate 		return (NULL);
2720Sstevel@tonic-gate 	}
2730Sstevel@tonic-gate 	fd = open(file, O_RDONLY);
2740Sstevel@tonic-gate 	if (fd < 0)
2750Sstevel@tonic-gate 		return (NULL);
2760Sstevel@tonic-gate 	h = (bstreamhandle)my_zalloc(sizeof (*h));
2770Sstevel@tonic-gate 	h->bstr_fd = fd;
2780Sstevel@tonic-gate 	h->bstr_read = file_stream_read;
2790Sstevel@tonic-gate 	h->bstr_close = file_stream_close;
2800Sstevel@tonic-gate 	h->bstr_size = file_stream_size;
2810Sstevel@tonic-gate 	h->bstr_rewind = file_stream_rewind;
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	return (h);
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate bstreamhandle
open_iso_read_stream(char * fname)287*4274Szk194757 open_iso_read_stream(char *fname)
288*4274Szk194757 {
289*4274Szk194757 	bstreamhandle h;
290*4274Szk194757 	off_t iso_size = 0;
291*4274Szk194757 	char iso_desc[ISO9660_PRIMARY_DESC_SIZE];
292*4274Szk194757 
293*4274Szk194757 	h = open_file_read_stream(fname);
294*4274Szk194757 
295*4274Szk194757 	/* If we don't have a valid handle immediately return NULL */
296*4274Szk194757 	if (h == NULL)
297*4274Szk194757 		return (NULL);
298*4274Szk194757 
299*4274Szk194757 	if (debug)
300*4274Szk194757 		(void) printf("Checking the ISO 9660 file header\n");
301*4274Szk194757 
302*4274Szk194757 	/* Check to see if we have a valid sized ISO image */
303*4274Szk194757 	h->bstr_size(h, &iso_size);
304*4274Szk194757 	if (iso_size < ISO9660_HEADER_SIZE) {
305*4274Szk194757 		if (debug)
306*4274Szk194757 			(void) printf("ISO 9660 header size not sane.\n");
307*4274Szk194757 		h->bstr_close(h);
308*4274Szk194757 		str_errno = STR_ERR_ISO_BAD_HEADER;
309*4274Szk194757 		return (NULL);
310*4274Szk194757 	}
311*4274Szk194757 
312*4274Szk194757 	if (debug)
313*4274Szk194757 		(void) printf("ISO 9660 header size is sane.\n");
314*4274Szk194757 
315*4274Szk194757 	/* Skip over the boot block sector of the ISO. */
316*4274Szk194757 	(void) lseek(h->bstr_fd, ISO9660_BOOT_BLOCK_SIZE, SEEK_SET);
317*4274Szk194757 
318*4274Szk194757 	/*
319*4274Szk194757 	 * Try to read in the ISO Descriptor and validate this
320*4274Szk194757 	 * is in fact an ISO 9660 image.
321*4274Szk194757 	 */
322*4274Szk194757 	if (read(h->bstr_fd, iso_desc, ISO9660_PRIMARY_DESC_SIZE) ==
323*4274Szk194757 	    ISO9660_PRIMARY_DESC_SIZE) {
324*4274Szk194757 		/*
325*4274Szk194757 		 * Bytes one through five of a valid ISO 9660 cd image
326*4274Szk194757 		 * should contain the string CD001. High Sierra format,
327*4274Szk194757 		 * the ISO 9660 predecessor, fills this field with the
328*4274Szk194757 		 * string CDROM. If neither is the case then we should
329*4274Szk194757 		 * close the stream, set str_errno, and return NULL.
330*4274Szk194757 		 */
331*4274Szk194757 		if (strncmp(iso_desc + ISO9660_STD_IDENT_OFFSET, "CD001",
332*4274Szk194757 		    5) != 0 && strncmp(iso_desc + ISO9660_STD_IDENT_OFFSET,
333*4274Szk194757 		    "CDROM", 5) != 0) {
334*4274Szk194757 			if (debug)
335*4274Szk194757 				(void) printf("Invalid ISO 9660 identifier.\n");
336*4274Szk194757 			h->bstr_close(h);
337*4274Szk194757 			str_errno = STR_ERR_ISO_BAD_HEADER;
338*4274Szk194757 			return (NULL);
339*4274Szk194757 		}
340*4274Szk194757 	} else {
341*4274Szk194757 		h->bstr_close(h);
342*4274Szk194757 		str_errno = STR_ERR_ISO_READ_ERR;
343*4274Szk194757 		return (NULL);
344*4274Szk194757 	}
345*4274Szk194757 
346*4274Szk194757 	/*
347*4274Szk194757 	 * Our ISO image is valid rewind the stream
348*4274Szk194757 	 * and return the handle.
349*4274Szk194757 	 */
350*4274Szk194757 	if (debug)
351*4274Szk194757 		(void) printf("ISO 9660 header is sane.\n");
352*4274Szk194757 	h->bstr_rewind(h);
353*4274Szk194757 	return (h);
354*4274Szk194757 }
355*4274Szk194757 
356*4274Szk194757 bstreamhandle
open_stdin_read_stream(void)3570Sstevel@tonic-gate open_stdin_read_stream(void)
3580Sstevel@tonic-gate {
3590Sstevel@tonic-gate 	bstreamhandle h;
3600Sstevel@tonic-gate 	int mode;
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	str_errno = 0;
3630Sstevel@tonic-gate 	if ((mode = fcntl(0, F_GETFD, NULL)) < 0) {
3640Sstevel@tonic-gate 		str_errno = STR_ERR_NO_READ_STDIN;
3650Sstevel@tonic-gate 		return (NULL);
3660Sstevel@tonic-gate 	}
3670Sstevel@tonic-gate 	mode &= 3;
3680Sstevel@tonic-gate 	if ((mode != O_RDONLY) && (mode != O_RDWR)) {
3690Sstevel@tonic-gate 		str_errno = STR_ERR_NO_READ_STDIN;
3700Sstevel@tonic-gate 		return (NULL);
3710Sstevel@tonic-gate 	}
3720Sstevel@tonic-gate 	h = (bstreamhandle)my_zalloc(sizeof (*h));
3730Sstevel@tonic-gate 	h->bstr_fd = 0;
3740Sstevel@tonic-gate 	h->bstr_read = file_stream_read;
3750Sstevel@tonic-gate 	h->bstr_close = stdin_stream_close;
3760Sstevel@tonic-gate 	h->bstr_size = file_stream_size;
3770Sstevel@tonic-gate 	h->bstr_rewind = stdin_stream_rewind;
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	return (h);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate bstreamhandle
open_au_read_stream(char * fname)3830Sstevel@tonic-gate open_au_read_stream(char *fname)
3840Sstevel@tonic-gate {
3850Sstevel@tonic-gate 	bstreamhandle h;
3860Sstevel@tonic-gate 	int fd, sav;
3870Sstevel@tonic-gate 	au_filehdr_t *au;
3880Sstevel@tonic-gate 	struct stat st;
3890Sstevel@tonic-gate 	uint32_t data_size;
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	au = NULL;
3920Sstevel@tonic-gate 	str_errno = 0;
3930Sstevel@tonic-gate 	fd = open(fname, O_RDONLY);
3940Sstevel@tonic-gate 	if (fd < 0)
3950Sstevel@tonic-gate 		return (NULL);
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	if (fstat(fd, &st) < 0) {
3980Sstevel@tonic-gate 		goto au_open_failed;
3990Sstevel@tonic-gate 	}
4000Sstevel@tonic-gate 	if ((st.st_mode & S_IFMT) != S_IFREG) {
4010Sstevel@tonic-gate 		str_errno = STR_ERR_NO_REG_FILE;
4020Sstevel@tonic-gate 		goto au_open_failed;
4030Sstevel@tonic-gate 	}
4040Sstevel@tonic-gate 	au = (au_filehdr_t *)my_zalloc(sizeof (*au));
4050Sstevel@tonic-gate 	if (read(fd, au, sizeof (*au)) != sizeof (*au)) {
4060Sstevel@tonic-gate 		str_errno = STR_ERR_AU_READ_ERR;
4070Sstevel@tonic-gate 		goto au_open_failed;
4080Sstevel@tonic-gate 	}
4090Sstevel@tonic-gate 	au->au_magic = BE32_TO_CPU(au->au_magic);
4100Sstevel@tonic-gate 	au->au_offset = BE32_TO_CPU(au->au_offset);
4110Sstevel@tonic-gate 	au->au_data_size = BE32_TO_CPU(au->au_data_size);
4120Sstevel@tonic-gate 	au->au_encoding = BE32_TO_CPU(au->au_encoding);
4130Sstevel@tonic-gate 	au->au_sample_rate = BE32_TO_CPU(au->au_sample_rate);
4140Sstevel@tonic-gate 	au->au_channels = BE32_TO_CPU(au->au_channels);
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	if (au->au_magic != AUDIO_AU_FILE_MAGIC) {
4170Sstevel@tonic-gate 		str_errno = STR_ERR_AU_BAD_HEADER;
4180Sstevel@tonic-gate 		goto au_open_failed;
4190Sstevel@tonic-gate 	}
4200Sstevel@tonic-gate 	if ((au->au_encoding != AUDIO_AU_ENCODING_LINEAR_16) ||
4210Sstevel@tonic-gate 	    (au->au_sample_rate != 44100) || (au->au_channels != 2)) {
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 		str_errno = STR_ERR_AU_UNSUPPORTED_FORMAT;
4240Sstevel@tonic-gate 		goto au_open_failed;
4250Sstevel@tonic-gate 	}
4260Sstevel@tonic-gate 	if (au->au_data_size != AUDIO_AU_UNKNOWN_SIZE) {
4270Sstevel@tonic-gate 		if ((au->au_offset + au->au_data_size) != st.st_size) {
4280Sstevel@tonic-gate 			str_errno = STR_ERR_AU_BAD_HEADER;
4290Sstevel@tonic-gate 			goto au_open_failed;
4300Sstevel@tonic-gate 		}
4310Sstevel@tonic-gate 		data_size = au->au_data_size;
4320Sstevel@tonic-gate 	} else {
4330Sstevel@tonic-gate 		data_size = st.st_size - au->au_offset;
4340Sstevel@tonic-gate 	}
4350Sstevel@tonic-gate 	if (data_size == 0) {
4360Sstevel@tonic-gate 		str_errno = STR_ERR_AU_UNSUPPORTED_FORMAT;
4370Sstevel@tonic-gate 		goto au_open_failed;
4380Sstevel@tonic-gate 	}
4390Sstevel@tonic-gate 	if (lseek(fd, au->au_offset, SEEK_SET) < 0) {
4400Sstevel@tonic-gate 		goto au_open_failed;
4410Sstevel@tonic-gate 	}
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	free(au);
4440Sstevel@tonic-gate 	h = (bstreamhandle)my_zalloc(sizeof (*h));
4450Sstevel@tonic-gate 	h->bstr_fd = fd;
4460Sstevel@tonic-gate 	h->bstr_read = file_stream_read_wrbo;
4470Sstevel@tonic-gate 	h->bstr_close = file_stream_close;
4480Sstevel@tonic-gate 	h->bstr_size = audio_stream_size;
4490Sstevel@tonic-gate 	h->bstr_rewind = au_stream_rewind;
4500Sstevel@tonic-gate 	h->bstr_private = (void *)data_size;
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	return (h);
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate au_open_failed:
4550Sstevel@tonic-gate 	sav = errno;
4560Sstevel@tonic-gate 	(void) close(fd);
4570Sstevel@tonic-gate 	if (au != NULL)
4580Sstevel@tonic-gate 		free(au);
4590Sstevel@tonic-gate 	errno = sav;
4600Sstevel@tonic-gate 	return (NULL);
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate bstreamhandle
open_wav_read_stream(char * fname)4640Sstevel@tonic-gate open_wav_read_stream(char *fname)
4650Sstevel@tonic-gate {
4660Sstevel@tonic-gate 	bstreamhandle h;
4670Sstevel@tonic-gate 	int fd, sav;
4680Sstevel@tonic-gate 	Wave_filehdr *wav;
4690Sstevel@tonic-gate 	struct stat st;
4700Sstevel@tonic-gate 	uint32_t data_size;
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	wav = NULL;
4730Sstevel@tonic-gate 	str_errno = 0;
4740Sstevel@tonic-gate 	fd = open(fname, O_RDONLY);
4750Sstevel@tonic-gate 	if (fd < 0)
4760Sstevel@tonic-gate 		return (NULL);
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	if (fstat(fd, &st) < 0) {
4790Sstevel@tonic-gate 		goto wav_open_failed;
4800Sstevel@tonic-gate 	}
4810Sstevel@tonic-gate 	if ((st.st_mode & S_IFMT) != S_IFREG) {
4820Sstevel@tonic-gate 		str_errno = STR_ERR_NO_REG_FILE;
4830Sstevel@tonic-gate 		goto wav_open_failed;
4840Sstevel@tonic-gate 	}
4850Sstevel@tonic-gate 	wav = (Wave_filehdr *)my_zalloc(sizeof (*wav));
4860Sstevel@tonic-gate 	if (read(fd, wav, sizeof (*wav)) != sizeof (*wav)) {
4870Sstevel@tonic-gate 		str_errno = STR_ERR_WAV_READ_ERR;
4880Sstevel@tonic-gate 		goto wav_open_failed;
4890Sstevel@tonic-gate 	}
4900Sstevel@tonic-gate 	if ((strncmp(wav->riff, "RIFF", 4) != 0) ||
4910Sstevel@tonic-gate 		(strncmp(wav->wave, "WAVE", 4) != 0)) {
4920Sstevel@tonic-gate 		str_errno = STR_ERR_WAV_BAD_HEADER;
4930Sstevel@tonic-gate 		goto wav_open_failed;
4940Sstevel@tonic-gate 	}
4950Sstevel@tonic-gate 	if (((CPU_TO_LE32(wav->total_chunk_size) + 8) != st.st_size) ||
4960Sstevel@tonic-gate 	    (strncmp(wav->fmt, "fmt ", 4) != 0) ||
4970Sstevel@tonic-gate 	    (CPU_TO_LE16(wav->fmt_tag) != 1) ||
4980Sstevel@tonic-gate 	    (CPU_TO_LE16(wav->n_channels) != 2) ||
4990Sstevel@tonic-gate 	    (CPU_TO_LE32(wav->sample_rate) != 44100) ||
5000Sstevel@tonic-gate 	    (CPU_TO_LE16(wav->bits_per_sample) != 16) ||
5010Sstevel@tonic-gate 	    (strncmp(wav->data, "data", 4) != 0) ||
5020Sstevel@tonic-gate 	    ((CPU_TO_LE32(wav->data_size) + 44) != st.st_size)) {
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 		str_errno = STR_ERR_WAV_UNSUPPORTED_FORMAT;
5050Sstevel@tonic-gate 		goto wav_open_failed;
5060Sstevel@tonic-gate 	}
5070Sstevel@tonic-gate 	data_size = CPU_TO_LE32(wav->data_size);
5080Sstevel@tonic-gate 	if (lseek(fd, sizeof (*wav), SEEK_SET) < 0) {
5090Sstevel@tonic-gate 		goto wav_open_failed;
5100Sstevel@tonic-gate 	}
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 	free(wav);
5130Sstevel@tonic-gate 	h = (bstreamhandle)my_zalloc(sizeof (*h));
5140Sstevel@tonic-gate 	h->bstr_fd = fd;
5150Sstevel@tonic-gate 	h->bstr_read = file_stream_read;
5160Sstevel@tonic-gate 	h->bstr_close = file_stream_close;
5170Sstevel@tonic-gate 	h->bstr_size = audio_stream_size;
5180Sstevel@tonic-gate 	h->bstr_rewind = wav_stream_rewind;
5190Sstevel@tonic-gate 	h->bstr_private = (void *)data_size;
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	return (h);
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate wav_open_failed:
5240Sstevel@tonic-gate 	sav = errno;
5250Sstevel@tonic-gate 	(void) close(fd);
5260Sstevel@tonic-gate 	if (wav != NULL)
5270Sstevel@tonic-gate 		free(wav);
5280Sstevel@tonic-gate 	errno = sav;
5290Sstevel@tonic-gate 	return (NULL);
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate bstreamhandle
open_aur_read_stream(char * fname)5330Sstevel@tonic-gate open_aur_read_stream(char *fname)
5340Sstevel@tonic-gate {
5350Sstevel@tonic-gate 	bstreamhandle h;
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	h = open_file_read_stream(fname);
5380Sstevel@tonic-gate 	if (h != NULL) {
5390Sstevel@tonic-gate 		h->bstr_read = file_stream_read_wrbo;
5400Sstevel@tonic-gate 	}
5410Sstevel@tonic-gate 	return (h);
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate bstreamhandle
open_au_write_stream(char * fname)5450Sstevel@tonic-gate open_au_write_stream(char *fname)
5460Sstevel@tonic-gate {
5470Sstevel@tonic-gate 	bstreamhandle h;
5480Sstevel@tonic-gate 	int esav, fd;
5490Sstevel@tonic-gate 	uchar_t head[] = PRE_DEF_AU_HDR;
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	str_errno = 0;
5520Sstevel@tonic-gate 	fd = -1;
5530Sstevel@tonic-gate 	/* O_RDWR because we need to read while closing */
5540Sstevel@tonic-gate 	fd = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
5550Sstevel@tonic-gate 	if (fd < 0)
5560Sstevel@tonic-gate 		goto open_au_write_stream_failed;
5570Sstevel@tonic-gate 	if (write(fd, head, PRE_DEF_AU_HDR_LEN) != PRE_DEF_AU_HDR_LEN) {
5580Sstevel@tonic-gate 		goto open_au_write_stream_failed;
5590Sstevel@tonic-gate 	}
5600Sstevel@tonic-gate 	h = (bstreamhandle)my_zalloc(sizeof (*h));
5610Sstevel@tonic-gate 	h->bstr_fd = fd;
5620Sstevel@tonic-gate 	h->bstr_write = file_stream_write_wrbo;
5630Sstevel@tonic-gate 	h->bstr_close = au_write_stream_close;
5640Sstevel@tonic-gate 	return (h);
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate open_au_write_stream_failed:
5670Sstevel@tonic-gate 	esav = errno;
5680Sstevel@tonic-gate 	if (fd != -1)
5690Sstevel@tonic-gate 		(void) close(fd);
5700Sstevel@tonic-gate 	errno = esav;
5710Sstevel@tonic-gate 	return (NULL);
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate bstreamhandle
open_wav_write_stream(char * fname)5750Sstevel@tonic-gate open_wav_write_stream(char *fname)
5760Sstevel@tonic-gate {
5770Sstevel@tonic-gate 	bstreamhandle h;
5780Sstevel@tonic-gate 	int esav, fd;
5790Sstevel@tonic-gate 	uchar_t head[] = PRE_DEF_WAV_HDR;
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	str_errno = 0;
5820Sstevel@tonic-gate 	fd = -1;
5830Sstevel@tonic-gate 	fd = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
5840Sstevel@tonic-gate 	if (fd < 0)
5850Sstevel@tonic-gate 		goto open_wav_write_stream_failed;
5860Sstevel@tonic-gate 	if (write(fd, head, PRE_DEF_WAV_HDR_LEN) != PRE_DEF_WAV_HDR_LEN) {
5870Sstevel@tonic-gate 		goto open_wav_write_stream_failed;
5880Sstevel@tonic-gate 	}
5890Sstevel@tonic-gate 	h = (bstreamhandle)my_zalloc(sizeof (*h));
5900Sstevel@tonic-gate 	h->bstr_fd = fd;
5910Sstevel@tonic-gate 	h->bstr_write = file_stream_write;
5920Sstevel@tonic-gate 	h->bstr_close = wav_write_stream_close;
5930Sstevel@tonic-gate 	return (h);
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate open_wav_write_stream_failed:
5960Sstevel@tonic-gate 	esav = errno;
5970Sstevel@tonic-gate 	if (fd != -1)
5980Sstevel@tonic-gate 		(void) close(fd);
5990Sstevel@tonic-gate 	errno = esav;
6000Sstevel@tonic-gate 	return (NULL);
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate bstreamhandle
open_aur_write_stream(char * fname)6040Sstevel@tonic-gate open_aur_write_stream(char *fname)
6050Sstevel@tonic-gate {
6060Sstevel@tonic-gate 	bstreamhandle h;
6070Sstevel@tonic-gate 	int fd;
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	str_errno = 0;
6100Sstevel@tonic-gate 	fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
6110Sstevel@tonic-gate 	if (fd < 0)
6120Sstevel@tonic-gate 		return (NULL);
6130Sstevel@tonic-gate 	h = (bstreamhandle)my_zalloc(sizeof (*h));
6140Sstevel@tonic-gate 	h->bstr_fd = fd;
6150Sstevel@tonic-gate 	h->bstr_write = file_stream_write_wrbo;
6160Sstevel@tonic-gate 	h->bstr_close = file_stream_close;
6170Sstevel@tonic-gate 	return (h);
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate bstreamhandle
open_file_write_stream(char * fname)6210Sstevel@tonic-gate open_file_write_stream(char *fname)
6220Sstevel@tonic-gate {
6230Sstevel@tonic-gate 	bstreamhandle h;
6240Sstevel@tonic-gate 	int fd;
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 	str_errno = 0;
6270Sstevel@tonic-gate 	fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
6280Sstevel@tonic-gate 	if (fd < 0)
6290Sstevel@tonic-gate 		return (NULL);
6300Sstevel@tonic-gate 	h = (bstreamhandle)my_zalloc(sizeof (*h));
6310Sstevel@tonic-gate 	h->bstr_fd = fd;
6320Sstevel@tonic-gate 	h->bstr_write = file_stream_write;
6330Sstevel@tonic-gate 	h->bstr_close = file_stream_close;
6340Sstevel@tonic-gate 	return (h);
6350Sstevel@tonic-gate }
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate bstreamhandle
open_temp_file_stream(void)6380Sstevel@tonic-gate open_temp_file_stream(void)
6390Sstevel@tonic-gate {
6400Sstevel@tonic-gate 	bstreamhandle h;
6410Sstevel@tonic-gate 	char *t;
6420Sstevel@tonic-gate 	int fd;
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate 	str_errno = 0;
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	t = (char *)get_tmp_name();
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 	if (strlcat(t, "/cdXXXXXX", PATH_MAX) >= PATH_MAX)
6490Sstevel@tonic-gate 		return (NULL);
6500Sstevel@tonic-gate 
6510Sstevel@tonic-gate 	fd = mkstemp(t);
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 	if (debug)
6540Sstevel@tonic-gate 		(void) printf("temp is: %s length: %d\n", t, strlen(t));
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 	if (fd < 0)
6570Sstevel@tonic-gate 		return (NULL);
6580Sstevel@tonic-gate 	(void) unlink(t);
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 	h = (bstreamhandle)my_zalloc(sizeof (*h));
6610Sstevel@tonic-gate 	h->bstr_fd = fd;
6620Sstevel@tonic-gate 	h->bstr_read = file_stream_read;
6630Sstevel@tonic-gate 	h->bstr_write = file_stream_write;
6640Sstevel@tonic-gate 	h->bstr_close = file_stream_close;
6650Sstevel@tonic-gate 	h->bstr_size = file_stream_size;
6660Sstevel@tonic-gate 	h->bstr_rewind = file_stream_rewind;
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 	return (h);
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate 
671472Sec158148 /*
672472Sec158148  * check_avail_temp_space returns 0 if there is adequate space
673472Sec158148  * in the temporary directory, or a non-zero error code if
674472Sec158148  * something goes wrong
675472Sec158148  */
6760Sstevel@tonic-gate int
check_avail_temp_space(size_t req_size)677472Sec158148 check_avail_temp_space(size_t req_size)
6780Sstevel@tonic-gate {
6790Sstevel@tonic-gate 	struct statvfs buf;
6802523Szk194757 	u_longlong_t free_size = 0;
6810Sstevel@tonic-gate 
682472Sec158148 	if (statvfs(get_tmp_name(), &buf) < 0) {
683472Sec158148 		return (errno);
684472Sec158148 	}
6850Sstevel@tonic-gate 
686472Sec158148 	free_size = buf.f_bfree * buf.f_frsize;
6870Sstevel@tonic-gate 
688472Sec158148 	if (free_size <= req_size)
689472Sec158148 		return (ENOMEM);
690472Sec158148 
691472Sec158148 	return (0);
6920Sstevel@tonic-gate }
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate char *
get_tmp_name(void)6960Sstevel@tonic-gate get_tmp_name(void)
6970Sstevel@tonic-gate {
6980Sstevel@tonic-gate 	char *t;
6990Sstevel@tonic-gate 	char *envptr;
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	t = (char *)my_zalloc(PATH_MAX);
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate 	/*
7040Sstevel@tonic-gate 	 * generate temp directory path based on this order:
7050Sstevel@tonic-gate 	 * user specified (-m option), temp env variable,
7060Sstevel@tonic-gate 	 * and finally /tmp if nothing is found.
7070Sstevel@tonic-gate 	 */
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate 	if (alt_tmp_dir) {
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 		/* copy and leave room for temp filename */
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 		(void) strlcpy(t, alt_tmp_dir, PATH_MAX - 10);
7140Sstevel@tonic-gate 	} else {
7150Sstevel@tonic-gate 		envptr = getenv("TMPDIR");
7160Sstevel@tonic-gate 		if (envptr != NULL) {
7170Sstevel@tonic-gate 			(void) strlcpy(t, envptr, PATH_MAX - 10);
7180Sstevel@tonic-gate 		} else {
7190Sstevel@tonic-gate 			(void) strlcpy(t, "/tmp", 5);
7200Sstevel@tonic-gate 		}
7210Sstevel@tonic-gate 	}
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate 	/*
7240Sstevel@tonic-gate 	 * no need to check if path is valid. statvfs will catch
7250Sstevel@tonic-gate 	 * it later and fail with a proper error message.
7260Sstevel@tonic-gate 	 */
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 	return (t);
7290Sstevel@tonic-gate }
730