|
|
@@ -174,7 +174,9 @@ namespace System.IO
|
|
|
throw new NotSupportedException("The stream does not support seeking");
|
|
|
}
|
|
|
|
|
|
- return(buf_start + buf_offset);
|
|
|
+ lock(this) {
|
|
|
+ return(buf_start + buf_offset);
|
|
|
+ }
|
|
|
}
|
|
|
set {
|
|
|
if(CanSeek == false) {
|
|
|
@@ -194,93 +196,108 @@ namespace System.IO
|
|
|
}
|
|
|
|
|
|
// methods
|
|
|
-
|
|
|
- public override int ReadByte ()
|
|
|
- {
|
|
|
- if (buf_offset >= buf_length) {
|
|
|
- RefillBuffer ();
|
|
|
-
|
|
|
- if (buf_length == 0)
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- return buf [buf_offset ++];
|
|
|
- }
|
|
|
-
|
|
|
- public override void WriteByte (byte value)
|
|
|
- {
|
|
|
- if (buf_offset == buf_size)
|
|
|
- FlushBuffer ();
|
|
|
-
|
|
|
- buf [buf_offset ++] = value;
|
|
|
- if (buf_offset > buf_length)
|
|
|
- buf_length = buf_offset;
|
|
|
-
|
|
|
- buf_dirty = true;
|
|
|
- }
|
|
|
+
|
|
|
+ public override int ReadByte ()
|
|
|
+ {
|
|
|
+ lock(this) {
|
|
|
+ if (buf_offset >= buf_length) {
|
|
|
+ RefillBuffer ();
|
|
|
+
|
|
|
+ if (buf_length == 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return(buf [buf_offset ++]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public override void WriteByte (byte value)
|
|
|
+ {
|
|
|
+ lock(this) {
|
|
|
+ if (buf_offset == buf_size) {
|
|
|
+ FlushBuffer ();
|
|
|
+ }
|
|
|
+
|
|
|
+ buf [buf_offset ++] = value;
|
|
|
+ if (buf_offset > buf_length) {
|
|
|
+ buf_length = buf_offset;
|
|
|
+ }
|
|
|
+
|
|
|
+ buf_dirty = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
public override int Read (byte[] dest, int dest_offset, int count)
|
|
|
{
|
|
|
int copied = 0;
|
|
|
|
|
|
- int n = ReadSegment (dest, dest_offset, count);
|
|
|
- copied += n;
|
|
|
- count -= n;
|
|
|
+ lock(this) {
|
|
|
+ int n = ReadSegment (dest, dest_offset, count);
|
|
|
+ copied += n;
|
|
|
+ count -= n;
|
|
|
|
|
|
- if (count == 0) {
|
|
|
- /* If there was already enough
|
|
|
- * buffered, no need to read more from
|
|
|
- * the file.
|
|
|
- */
|
|
|
- return (copied);
|
|
|
- }
|
|
|
+ if (count == 0) {
|
|
|
+ /* If there was already enough
|
|
|
+ * buffered, no need to read
|
|
|
+ * more from the file.
|
|
|
+ */
|
|
|
+ return (copied);
|
|
|
+ }
|
|
|
|
|
|
- if (count > buf_size) {
|
|
|
- /* Read as much as we can, up to count
|
|
|
- * bytes
|
|
|
- */
|
|
|
- FlushBuffer();
|
|
|
- n = ReadData (handle, dest,
|
|
|
- dest_offset+copied, count);
|
|
|
+ if (count > buf_size) {
|
|
|
+ /* Read as much as we can, up
|
|
|
+ * to count bytes
|
|
|
+ */
|
|
|
+ FlushBuffer();
|
|
|
+ n = ReadData (handle, dest,
|
|
|
+ dest_offset+copied,
|
|
|
+ count);
|
|
|
|
|
|
- /* Make the next buffer read start
|
|
|
- * from the right place
|
|
|
- */
|
|
|
- buf_start += n;
|
|
|
- } else {
|
|
|
- RefillBuffer ();
|
|
|
- n = ReadSegment (dest, dest_offset+copied,
|
|
|
- count);
|
|
|
- }
|
|
|
+ /* Make the next buffer read
|
|
|
+ * start from the right place
|
|
|
+ */
|
|
|
+ buf_start += n;
|
|
|
+ } else {
|
|
|
+ RefillBuffer ();
|
|
|
+ n = ReadSegment (dest,
|
|
|
+ dest_offset+copied,
|
|
|
+ count);
|
|
|
+ }
|
|
|
|
|
|
- copied += n;
|
|
|
+ copied += n;
|
|
|
|
|
|
- return(copied);
|
|
|
+ return(copied);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public override void Write (byte[] src, int src_offset, int count)
|
|
|
- {
|
|
|
- int copied = 0;
|
|
|
- while (count > 0) {
|
|
|
- int n = WriteSegment (src, src_offset + copied, count);
|
|
|
- copied += n;
|
|
|
- count -= n;
|
|
|
-
|
|
|
- FlushBuffer ();
|
|
|
+ public override void Write (byte[] src, int src_offset, int count)
|
|
|
+ {
|
|
|
+ int copied = 0;
|
|
|
|
|
|
- if (count == 0)
|
|
|
- break;
|
|
|
+ lock(this) {
|
|
|
+ while (count > 0) {
|
|
|
+ int n = WriteSegment (src, src_offset + copied, count);
|
|
|
+ copied += n;
|
|
|
+ count -= n;
|
|
|
|
|
|
- if (count > buf_size) {
|
|
|
- // shortcut for long writes
|
|
|
- MonoIOError error;
|
|
|
+ FlushBuffer ();
|
|
|
+
|
|
|
+ if (count == 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (count > buf_size) {
|
|
|
+ // shortcut for long writes
|
|
|
+ MonoIOError error;
|
|
|
|
|
|
- MonoIO.Write (handle, src, src_offset + copied, count, out error);
|
|
|
- buf_start += count;
|
|
|
- break;
|
|
|
+ MonoIO.Write (handle, src, src_offset + copied, count, out error);
|
|
|
+ buf_start += count;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
public override long Seek (long offset, SeekOrigin origin)
|
|
|
{
|
|
|
@@ -292,45 +309,49 @@ namespace System.IO
|
|
|
throw new NotSupportedException("The stream does not support seeking");
|
|
|
}
|
|
|
|
|
|
- switch (origin) {
|
|
|
- case SeekOrigin.End:
|
|
|
- pos = Length + offset;
|
|
|
- break;
|
|
|
-
|
|
|
- case SeekOrigin.Current:
|
|
|
- pos = Position + offset;
|
|
|
- break;
|
|
|
-
|
|
|
- case SeekOrigin.Begin: default:
|
|
|
- pos = offset;
|
|
|
- break;
|
|
|
- }
|
|
|
+ lock(this) {
|
|
|
+ switch (origin) {
|
|
|
+ case SeekOrigin.End:
|
|
|
+ pos = Length + offset;
|
|
|
+ break;
|
|
|
|
|
|
- if (pos < 0) {
|
|
|
- /* LAMESPEC: shouldn't this be
|
|
|
- * ArgumentOutOfRangeException?
|
|
|
- */
|
|
|
- throw new ArgumentException("Attempted to Seek before the beginning of the stream");
|
|
|
- }
|
|
|
+ case SeekOrigin.Current:
|
|
|
+ pos = Position + offset;
|
|
|
+ break;
|
|
|
|
|
|
- if(pos < this.append_startpos) {
|
|
|
- /* More undocumented crap */
|
|
|
- throw new IOException("Can't seek back over pre-existing data in append mode");
|
|
|
- }
|
|
|
-
|
|
|
- if (pos >= buf_start && pos <= buf_start + buf_length) {
|
|
|
- buf_offset = (int) (pos - buf_start);
|
|
|
- return pos;
|
|
|
- }
|
|
|
+ case SeekOrigin.Begin: default:
|
|
|
+ pos = offset;
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- FlushBuffer ();
|
|
|
+ if (pos < 0) {
|
|
|
+ /* LAMESPEC: shouldn't this be
|
|
|
+ * ArgumentOutOfRangeException?
|
|
|
+ */
|
|
|
+ throw new ArgumentException("Attempted to Seek before the beginning of the stream");
|
|
|
+ }
|
|
|
|
|
|
- MonoIOError error;
|
|
|
-
|
|
|
- buf_start = MonoIO.Seek (handle, pos,
|
|
|
- SeekOrigin.Begin, out error);
|
|
|
+ if(pos < this.append_startpos) {
|
|
|
+ /* More undocumented crap */
|
|
|
+ throw new IOException("Can't seek back over pre-existing data in append mode");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pos >= buf_start &&
|
|
|
+ pos <= buf_start + buf_length) {
|
|
|
+ buf_offset = (int) (pos - buf_start);
|
|
|
+ return pos;
|
|
|
+ }
|
|
|
+
|
|
|
+ FlushBuffer ();
|
|
|
|
|
|
- return buf_start;
|
|
|
+ MonoIOError error;
|
|
|
+
|
|
|
+ buf_start = MonoIO.Seek (handle, pos,
|
|
|
+ SeekOrigin.Begin,
|
|
|
+ out error);
|
|
|
+
|
|
|
+ return(buf_start);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public override void SetLength (long length)
|
|
|
@@ -354,17 +375,19 @@ namespace System.IO
|
|
|
MonoIO.SetLength (handle, length, out error);
|
|
|
}
|
|
|
|
|
|
- public override void Flush ()
|
|
|
- {
|
|
|
- FlushBuffer ();
|
|
|
-
|
|
|
- //
|
|
|
- // The flushing is not actually required, in the mono runtime we were
|
|
|
- // mapping flush to `fsync' which is not the same.
|
|
|
- //
|
|
|
- //MonoIO.Flush (handle);
|
|
|
- }
|
|
|
-
|
|
|
+ public override void Flush ()
|
|
|
+ {
|
|
|
+ lock(this) {
|
|
|
+ FlushBuffer ();
|
|
|
+ }
|
|
|
+
|
|
|
+ // The flushing is not actually required, in
|
|
|
+ //the mono runtime we were mapping flush to
|
|
|
+ //`fsync' which is not the same.
|
|
|
+ //
|
|
|
+ //MonoIO.Flush (handle);
|
|
|
+ }
|
|
|
+
|
|
|
public override void Close ()
|
|
|
{
|
|
|
Dispose (true);
|
|
|
@@ -380,7 +403,9 @@ namespace System.IO
|
|
|
|
|
|
protected virtual void Dispose (bool disposing) {
|
|
|
if (owner && handle != MonoIO.InvalidHandle) {
|
|
|
- FlushBuffer ();
|
|
|
+ lock(this) {
|
|
|
+ FlushBuffer ();
|
|
|
+ }
|
|
|
|
|
|
MonoIOError error;
|
|
|
|
|
|
@@ -394,62 +419,85 @@ namespace System.IO
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // private
|
|
|
-
|
|
|
- private int ReadSegment (byte [] dest, int dest_offset, int count)
|
|
|
- {
|
|
|
- if (count > buf_length - buf_offset)
|
|
|
- count = buf_length - buf_offset;
|
|
|
-
|
|
|
- if (count > 0) {
|
|
|
- Buffer.BlockCopy (buf, buf_offset, dest, dest_offset, count);
|
|
|
- buf_offset += count;
|
|
|
- }
|
|
|
-
|
|
|
- return count;
|
|
|
- }
|
|
|
-
|
|
|
- private int WriteSegment (byte [] src, int src_offset, int count)
|
|
|
- {
|
|
|
- if (count > buf_size - buf_offset)
|
|
|
- count = buf_size - buf_offset;
|
|
|
-
|
|
|
- if (count > 0) {
|
|
|
- Buffer.BlockCopy (src, src_offset, buf, buf_offset, count);
|
|
|
- buf_offset += count;
|
|
|
- if (buf_offset > buf_length)
|
|
|
- buf_length = buf_offset;
|
|
|
-
|
|
|
- buf_dirty = true;
|
|
|
- }
|
|
|
-
|
|
|
- return count;
|
|
|
- }
|
|
|
+ // private.
|
|
|
|
|
|
- private void FlushBuffer ()
|
|
|
+ // ReadSegment, WriteSegment, FlushBuffer,
|
|
|
+ // RefillBuffer and ReadData should only be called
|
|
|
+ // when the Monitor lock is held, but these methods
|
|
|
+ // grab it again just to be safe.
|
|
|
+
|
|
|
+ private int ReadSegment (byte [] dest, int dest_offset,
|
|
|
+ int count)
|
|
|
{
|
|
|
- if (buf_dirty) {
|
|
|
- MonoIOError error;
|
|
|
+ lock(this) {
|
|
|
+ if (count > buf_length - buf_offset) {
|
|
|
+ count = buf_length - buf_offset;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (count > 0) {
|
|
|
+ Buffer.BlockCopy (buf, buf_offset,
|
|
|
+ dest, dest_offset,
|
|
|
+ count);
|
|
|
+ buf_offset += count;
|
|
|
+ }
|
|
|
|
|
|
- if (CanSeek == true) {
|
|
|
- MonoIO.Seek (handle, buf_start,
|
|
|
- SeekOrigin.Begin,
|
|
|
- out error);
|
|
|
+ return(count);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int WriteSegment (byte [] src, int src_offset,
|
|
|
+ int count)
|
|
|
+ {
|
|
|
+ lock(this) {
|
|
|
+ if (count > buf_size - buf_offset) {
|
|
|
+ count = buf_size - buf_offset;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (count > 0) {
|
|
|
+ Buffer.BlockCopy (src, src_offset,
|
|
|
+ buf, buf_offset,
|
|
|
+ count);
|
|
|
+ buf_offset += count;
|
|
|
+ if (buf_offset > buf_length) {
|
|
|
+ buf_length = buf_offset;
|
|
|
+ }
|
|
|
+
|
|
|
+ buf_dirty = true;
|
|
|
}
|
|
|
- MonoIO.Write (handle, buf, 0, buf_length,
|
|
|
- out error);
|
|
|
+
|
|
|
+ return(count);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- buf_start += buf_length;
|
|
|
- buf_offset = buf_length = 0;
|
|
|
- buf_dirty = false;
|
|
|
+ private void FlushBuffer ()
|
|
|
+ {
|
|
|
+ lock(this) {
|
|
|
+ if (buf_dirty) {
|
|
|
+ MonoIOError error;
|
|
|
+
|
|
|
+ if (CanSeek == true) {
|
|
|
+ MonoIO.Seek (handle, buf_start,
|
|
|
+ SeekOrigin.Begin,
|
|
|
+ out error);
|
|
|
+ }
|
|
|
+ MonoIO.Write (handle, buf, 0,
|
|
|
+ buf_length, out error);
|
|
|
+ }
|
|
|
+
|
|
|
+ buf_start += buf_length;
|
|
|
+ buf_offset = buf_length = 0;
|
|
|
+ buf_dirty = false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private void RefillBuffer ()
|
|
|
{
|
|
|
- FlushBuffer();
|
|
|
+ lock(this) {
|
|
|
+ FlushBuffer();
|
|
|
|
|
|
- buf_length = ReadData (handle, buf, 0, buf_size);
|
|
|
+ buf_length = ReadData (handle, buf, 0,
|
|
|
+ buf_size);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private int ReadData (IntPtr handle, byte[] buf, int offset,
|
|
|
@@ -457,20 +505,22 @@ namespace System.IO
|
|
|
{
|
|
|
MonoIOError error;
|
|
|
|
|
|
- int amount = MonoIO.Read (handle, buf, offset, count,
|
|
|
- out error);
|
|
|
-
|
|
|
- /* Check for read error */
|
|
|
- if(amount == -1) {
|
|
|
- /* Kludge around broken pipes */
|
|
|
- if(error == MonoIOError.ERROR_BROKEN_PIPE) {
|
|
|
- amount = 0;
|
|
|
- } else {
|
|
|
- throw new IOException ();
|
|
|
+ lock(this) {
|
|
|
+ int amount = MonoIO.Read (handle, buf, offset,
|
|
|
+ count, out error);
|
|
|
+
|
|
|
+ /* Check for read error */
|
|
|
+ if(amount == -1) {
|
|
|
+ /* Kludge around broken pipes */
|
|
|
+ if(error == MonoIOError.ERROR_BROKEN_PIPE) {
|
|
|
+ amount = 0;
|
|
|
+ } else {
|
|
|
+ throw new IOException ();
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- return(amount);
|
|
|
+ return(amount);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|