/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // /////////////////////////////////////////////////////////////////////////////// using System; using System.IO; using Microsoft.Contracts; using Microsoft.Singularity; using Microsoft.Singularity.Channels; namespace Iso9660 { public class Iso9660FileStream { private Iso9660FileInfo _info; private long _pos = 0; [NotDelayed] public Iso9660FileStream(Iso9660FileInfo info, FileMode mode, FileAccess access) { _info = info; _pos = 0; } ~Iso9660FileStream() {} public bool CanRead { get { return true; } } public bool CanWrite { get { return false; } } public bool CanSeek { get { return true; } } public long Length { get { long size = (long)_info.size; return size; } } public long Position { get { return _pos; } } public void Close() { } public int Read(ByteContainer buffer, int offset, int count) { Tracing.Log(Tracing.Debug,"Entered"); long currentLength = (long)_info.size; // just touch the file if (count == 0 || _pos >= currentLength){ return 0; } long bytesLeft; if (currentLength - _pos > (long)count) { bytesLeft = (long)count; } else { bytesLeft = currentLength - _pos; } /*** Console.WriteLine("ReadArgs: count = " + args.count + " offset = " + args.offset + " bytes to be read " + bytesLeft); ***/ if (buffer == null) { //Console.WriteLine("ReadNFS: user buffer was null!"); throw new ArgumentNullException("Buffer given to Read was null"); } else if ((long)buffer.Length < bytesLeft) { throw new ArgumentException("Not enough room in buffer"); } long uBufOff = (long)offset; // offset into user's buffer; long curFileOff = _pos; long blockno = -1; while(bytesLeft > 0) { long curBlk = _info.BlockFromByte(curFileOff); long curBlkSize = Iso9660FileInfo.BlockSize(curBlk); long curBlkOff = curFileOff % curBlkSize; /*** Console.WriteLine("ReadArgs: curBlockNum " + curBlk + " curBlkSize = " + curBlkSize + " cur offset into blk " + curBlkOff); ***/ if (blockno < curBlk) { blockno = curBlk; // // 1. fetch data from media's block // Iso9660.Stdio.RawDevice.ReadBlock (_info.buf, (ulong)blockno); } long dist; if (curBlkSize - curBlkOff > bytesLeft) { dist = bytesLeft; } else { dist = curBlkSize - curBlkOff; } // // 2. store data into user's buffer // buffer.CopyTo (_info.buf, (int)curBlkOff, (int)uBufOff, (int)dist); uBufOff += dist; curFileOff += dist; bytesLeft -= dist; } _pos += uBufOff; return (int)uBufOff; Tracing.Log(Tracing.Debug,"Exit"); } public long Seek(long offset, System.IO.SeekOrigin origin) { Tracing.Log(Tracing.Debug,"Entered"); switch (origin) { case System.IO.SeekOrigin.Begin: if (offset >= 0) { _pos = offset; } break; case System.IO.SeekOrigin.Current: if (_pos + offset >= 0) { _pos += offset; } break; case System.IO.SeekOrigin.End: long len = this.Length; if (len + offset >= 0) { _pos = len + offset; } break; default: throw new NotSupportedException("Unidentified SeekOrigin argument"); } Tracing.Log(Tracing.Debug,"Exit"); return (long)_pos; } } }