singrdk/base/Services/Iso9660/Iso9660FileStream.cs

170 lines
5.0 KiB
C#

///////////////////////////////////////////////////////////////////////////////
//
// 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;
}
}
}