singrdk/base/Services/Iso9660/Iso9660DirectoryInfo.cs

157 lines
5.1 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections;
using Microsoft.Singularity.V1.Services;
using System;
using System.Collections;
using Microsoft.Singularity;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Drivers;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.V1.Services;
namespace Iso9660
{
public class Iso9660DirectoryInfo : Iso9660FileSystemInfo
{
private byte LEN { get { return buf[pos + DirEnt.LEN]; }}
private byte FLAGS { get { return buf[pos + DirEnt.FLAGS]; }}
private int NAME_LEN { get { return buf[pos + DirEnt.NAME_LEN]; }}
private int NAME_POS { get { return pos + DirEnt.NAME; }}
private string NAME { get { return ByteArray.ToString (buf, NAME_POS, NAME_LEN); }}
private bool DOT { get { return ((NAME_LEN == 1) && (buf[NAME_POS] == 0x00)); }}
private bool DOTDOT { get { return ((NAME_LEN == 1) && (buf[NAME_POS] == 0x01)); }}
public string myPrefix;
internal Iso9660DirectoryInfo() {}
//
// 0. Delegated "lookup" for Enumerate & FindChild
//
private delegate bool LOOKUP (Object obj);
private bool Lookup (LOOKUP lookup, Object obj) {
//
// The following assumes that the list of directory entries
// is terminated in every block by an entry with LEN 0, ie:
//
// 1. directory entries do not cross block boundaries
// (with <n> entries in the 1st block, and unused bytes at
// the end, entry <n+1> starts at pos 0 in the 2nd block)
//
// 2. the size is used only to calculate the number of blocks
// (not the last byte of the last entry in the last block)
//
ulong nblocks = 1 + (size - 1) / 2048;
for (ulong n = 0; n < nblocks; n++) {
Iso9660.Stdio.RawDevice.ReadBlock (buf, blockno + n);
for (pos = 0;; pos += LEN) {
if (LEN == 0)
break;
if (DOT || DOTDOT)
continue;
if (lookup (obj))
return true;
}
}
return false;
}
//
// 1. Enumerate (dir/ls)
//
private bool Enumerate (Object obj) {
bool dir = ((FLAGS & (byte)Iso9660FileFlags.Directory) != 0);
NodeType nodeType = (dir)? NodeType.Directory: NodeType.File;
((SortedList)obj).Add (NAME.ToLower(), nodeType); // FIXME: ToLower opt?
return false; // GetNextChild
}
public EnumerationRecords[] in ExHeap Enumerate (out ErrorCode errorOut)
{
SortedList matches;
EnumerationRecords[] in ExHeap responses = null;
errorOut = ErrorCode.NoError;
matches = new SortedList();
if (matches == null)
{
errorOut = ErrorCode.InsufficientResources;
return null;
}
Lookup (Enumerate, matches);
responses = new [ExHeap] EnumerationRecords[matches.Count];
if (responses == null)
{
errorOut = ErrorCode.InsufficientResources;
return null;
}
for (int i = 0; i < matches.Count; i++){
expose (responses[i]) {
delete responses[i].Path; // checker doesn't know its null.
responses[i].Path = Bitter.FromString2((!)((string)matches.GetKey(i)));
responses[i].Type = (NodeType) (!) matches.GetByIndex(i);
}
}
return responses;
}
//
// 2. FindChild
//
private bool FindChild (Object obj) {
return ((string)obj == NAME.ToLower()); // FIXME: ToLower opt?
}
internal bool FindChild(string name, bool returnChild,
out Iso9660FileSystemInfo child) {
if (!Lookup (FindChild, name)) {
child = null;
return false;
}
if ((FLAGS & (byte)Iso9660FileFlags.Directory) != 0) {
Iso9660DirectoryInfo dir = new Iso9660DirectoryInfo();
dir.myPrefix = myPrefix + SuperBlock.DELIMITER + name;
child = dir;
}
else {
Iso9660FileInfo file = new Iso9660FileInfo();
child = file;
}
child.InitializeMe (buf, pos);
return true;
}
}
}