From dcd2624f5ea938a880a64b29b8eebd93eb56f986 Mon Sep 17 00:00:00 2001
From: mrg <mrg@NetBSD.org>
Date: Tue, 13 Apr 1999 07:21:45 +0000
Subject: [PATCH] try using normal read/write is mmap() fails.  tell the VM
 system we are going to be doing sequential access via madvise().

---
 usr.bin/audio/play/play.c | 139 ++++++++++++++++++++++++--------------
 1 file changed, 90 insertions(+), 49 deletions(-)

diff --git a/usr.bin/audio/play/play.c b/usr.bin/audio/play/play.c
index 5d1b73466009..cd4dc6aaeca4 100644
--- a/usr.bin/audio/play/play.c
+++ b/usr.bin/audio/play/play.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: play.c,v 1.8 1999/04/02 16:05:55 augustss Exp $	*/
+/*	$NetBSD: play.c,v 1.9 1999/04/13 07:21:45 mrg Exp $	*/
 
 /*
  * Copyright (c) 1999 Matthew R. Green
@@ -47,6 +47,7 @@
 
 int main __P((int, char *[]));
 void usage __P((void));
+void play_fd __P((int, char *));
 ssize_t audioctl_write_fromhdr __P((void *, size_t, int));
 
 audio_info_t	info;
@@ -61,16 +62,17 @@ int	precision;
 int	channels;
 
 char	const *play_errstring = NULL;
+size_t	bufsize;
+int	audiofd, ctlfd;
 
 int
 main(argc, argv)
 	int argc;
 	char *argv[];
 {
-	size_t	len, bufsize;
-	ssize_t	hdrlen;
+	size_t	len;
 	off_t	filesize;
-	int	ch, audiofd, ctlfd;
+	int	ch;
 	int	iflag = 0;
 	int	qflag = 0;
 	int	verbose = 0;
@@ -160,11 +162,11 @@ main(argc, argv)
 
 	audiofd = open(device, O_WRONLY);
 #ifdef _PATH_OAUDIO
-        /* Allow the non-unit device to be used. */
-        if (audiofd < 0 && device == _PATH_AUDIO) {
-        	device = _PATH_OAUDIO;
-        	ctldev = _PATH_OAUDIOCTL;
-                audiofd = open(device, O_WRONLY);
+	/* Allow the non-unit device to be used. */
+	if (audiofd < 0 && device == _PATH_AUDIO) {
+		device = _PATH_OAUDIO;
+		ctldev = _PATH_OAUDIOCTL;
+		audiofd = open(device, O_WRONLY);
 	}
 #endif
 	if (audiofd < 0)
@@ -185,6 +187,8 @@ main(argc, argv)
 		void *addr, *oaddr;
 
 		do {
+			ssize_t	hdrlen;
+
 			fd = open(*argv, O_RDONLY);
 			if (fd < 0)
 				err(1, "could not open %s", *argv);
@@ -195,12 +199,30 @@ main(argc, argv)
 
 			oaddr = addr = mmap(0, (size_t)filesize, PROT_READ,
 			    MAP_SHARED, fd, 0);
-			if (addr == (void *)-1)
-				err(1, "could not mmap %s", *argv);
 
+			/*
+			 * if we failed to mmap the file, try to read it
+			 * instead, so that filesystems, etc, that do not
+			 * support mmap() work
+			 */
+			if (addr == (void *)-1) {
+				play_fd(fd, *argv);
+				close(fd);
+				continue;
+			}
+
+			/*
+			 * give the VM system a bit of a hint about the type
+			 * of accesses we will make.
+			 */
+			if (madvise(addr, filesize, MADV_SEQUENTIAL) < 0)
+				warn("madvise failed, ignoring");
+
+			/*
+			 * get the header length and set up the audio device
+			 */
 			if ((hdrlen = audioctl_write_fromhdr(addr,
 			    (size_t)filesize, ctlfd)) < 0) {
-play_error:
 				if (play_errstring)
 					errx(1, "%s: %s", play_errstring, *argv);
 				else
@@ -219,7 +241,8 @@ play_error:
 			if (write(audiofd, addr, (size_t)filesize) != (ssize_t)filesize)
 				err(1, "final write failed");
 
-			ioctl(audiofd, AUDIO_DRAIN);
+			if (ioctl(audiofd, AUDIO_DRAIN) < 0)
+				warn("audio drain ioctl failed");
 			if (munmap(oaddr, (size_t)filesize) < 0)
 				err(1, "munmap failed");
 
@@ -227,47 +250,65 @@ play_error:
 			
 		} while (*++argv);
 	} else {
-		char	*buffer = malloc(bufsize);
-		int	n, m;
-
-		if (buffer == NULL)
-			err(1, "malloc of read buffer failed");
-
-		n = read(STDIN_FILENO, buffer, bufsize);
-
-		if (n < 0)
-			err(1, "read of standard input failed");
-		if (n == 0)
-			errx(1, "EOF on standard input");
-
-		hdrlen = audioctl_write_fromhdr(buffer, n, ctlfd);
-		if (hdrlen < 0)
-			goto play_error;
-
-		/* advance the buffer if we have to */
-		if (hdrlen > 0) {
-			/* shouldn't happen */
-			if (hdrlen > n)
-				err(1, "bogus hdrlen %d > length %d?", (int)hdrlen, n);
-
-			memmove(buffer, buffer + hdrlen, n - hdrlen);
-
-			m = read(STDIN_FILENO, buffer + n, hdrlen);
-			n += m;
-		}
-		/* read until EOF or error */
-		do {
-			if (n == -1)
-				err(1, "read of standard input failed");
-			if (write(audiofd, buffer, n) != n)
-				err(1, "write failed");
-		} while ((n = read(STDIN_FILENO, buffer, bufsize)));
-		ioctl(audiofd, AUDIO_DRAIN);
+		play_fd(STDIN_FILENO, "standard input");
 	}
 
 	exit(0);
 }
 
+/*
+ * play the file on on the file descriptor fd
+ */
+void
+play_fd(fd, file)
+	int     fd;
+	char    *file;
+{
+	char    *buffer = malloc(bufsize);
+	ssize_t hdrlen;
+	int     n, m;
+
+	if (buffer == NULL)
+		err(1, "malloc of read buffer failed");
+
+	n = read(fd, buffer, bufsize);
+
+	if (n < 0)
+		err(1, "read of standard input failed");
+	if (n == 0)
+		errx(1, "EOF on standard input");
+
+	hdrlen = audioctl_write_fromhdr(buffer, n, ctlfd);
+	if (hdrlen < 0) {
+		if (play_errstring)
+			errx(1, "%s: %s", play_errstring, file);
+		else
+			errx(1, "unknown audio file: %s", file);
+	}
+
+	/* advance the buffer if we have to */
+	if (hdrlen > 0) {
+		/* shouldn't happen */
+		if (hdrlen > n)
+			err(1, "bogus hdrlen %d > length %d?", (int)hdrlen, n);
+
+		memmove(buffer, buffer + hdrlen, n - hdrlen);
+
+		m = read(fd, buffer + n, hdrlen);
+		n += m;
+	}
+	/* read until EOF or error */
+	do {
+		if (n == -1)
+			err(1, "read of standard input failed");
+		if (write(audiofd, buffer, n) != n)
+			err(1, "write failed");
+	} while ((n = read(fd, buffer, bufsize)));
+
+	if (ioctl(audiofd, AUDIO_DRAIN) < 0)
+		warn("audio drain ioctl failed");
+}
+
 /*
  * only support sun and wav audio files so far ...
  *