Issue #18950: Fix miscellaneous bugs in the sunau module.
Au_read.readframes() now updates current file position and reads correct
number of frames from multichannel stream.  Au_write.writeframesraw() now
correctly updates current file position.  Au_read and Au_write now correctly
work with file object if start file position is not a zero.
diff --git a/Lib/sunau.py b/Lib/sunau.py
index a04d8c0..4f0885a 100644
--- a/Lib/sunau.py
+++ b/Lib/sunau.py
@@ -203,6 +203,10 @@
                     break
         else:
             self._info = ''
+        try:
+            self._data_pos = file.tell()
+        except (AttributeError, IOError):
+            self._data_pos = None
 
     def getfp(self):
         return self._file
@@ -255,7 +259,8 @@
             if nframes == AUDIO_UNKNOWN_SIZE:
                 data = self._file.read()
             else:
-                data = self._file.read(nframes * self._framesize * self._nchannels)
+                data = self._file.read(nframes * self._framesize)
+            self._soundpos += len(data) // self._framesize
             if self._encoding == AUDIO_FILE_ENCODING_MULAW_8:
                 import audioop
                 data = audioop.ulaw2lin(data, self._sampwidth)
@@ -263,8 +268,10 @@
         return None             # XXX--not implemented yet
 
     def rewind(self):
+        if self._data_pos is None:
+            raise IOError('cannot seek')
+        self._file.seek(self._data_pos)
         self._soundpos = 0
-        self._file.seek(self._hdr_size)
 
     def tell(self):
         return self._soundpos
@@ -272,7 +279,9 @@
     def setpos(self, pos):
         if pos < 0 or pos > self.getnframes():
             raise Error, 'position not in range'
-        self._file.seek(pos * self._framesize + self._hdr_size)
+        if self._data_pos is None:
+            raise IOError('cannot seek')
+        self._file.seek(self._data_pos + pos * self._framesize)
         self._soundpos = pos
 
     def close(self):
@@ -382,10 +391,10 @@
 
     def writeframesraw(self, data):
         self._ensure_header_written()
-        nframes = len(data) / self._framesize
         if self._comptype == 'ULAW':
             import audioop
             data = audioop.lin2ulaw(data, self._sampwidth)
+        nframes = len(data) // self._framesize
         self._file.write(data)
         self._nframeswritten = self._nframeswritten + nframes
         self._datawritten = self._datawritten + len(data)
@@ -445,6 +454,10 @@
             length = AUDIO_UNKNOWN_SIZE
         else:
             length = self._nframes * self._framesize
+        try:
+            self._form_length_pos = self._file.tell()
+        except (AttributeError, IOError):
+            self._form_length_pos = None
         _write_u32(self._file, length)
         self._datalength = length
         _write_u32(self._file, encoding)
@@ -454,7 +467,9 @@
         self._file.write('\0'*(header_size - len(self._info) - 24))
 
     def _patchheader(self):
-        self._file.seek(8)
+        if self._form_length_pos is None:
+            raise IOError('cannot seek')
+        self._file.seek(self._form_length_pos)
         _write_u32(self._file, self._datawritten)
         self._datalength = self._datawritten
         self._file.seek(0, 2)