207 lines
7.2 KiB
Plaintext
207 lines
7.2 KiB
Plaintext
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: createfile.sg
|
||
|
//
|
||
|
// Note:
|
||
|
//
|
||
|
|
||
|
using FileSystem.Utils;
|
||
|
using System;
|
||
|
using System.Text;
|
||
|
using System.Threading;
|
||
|
using Microsoft.Singularity;
|
||
|
using Microsoft.Singularity.Directory;
|
||
|
using Microsoft.Singularity.Channels;
|
||
|
using Microsoft.Singularity.FileSystem;
|
||
|
using Microsoft.Singularity.V1.Services;
|
||
|
|
||
|
using Microsoft.Contracts;
|
||
|
using Microsoft.SingSharp.Reflection;
|
||
|
using Microsoft.Singularity.Applications;
|
||
|
using Microsoft.Singularity.Io;
|
||
|
using Microsoft.Singularity.Configuration;
|
||
|
using FileSystem.Utils;
|
||
|
|
||
|
[assembly: Transform(typeof(ApplicationResourceTransform))]
|
||
|
|
||
|
namespace Microsoft.Singularity.Applications
|
||
|
{
|
||
|
[ConsoleCategory(HelpMessage="create a new file", DefaultAction=true)]
|
||
|
internal class Parameters
|
||
|
{
|
||
|
[InputEndpoint("data")]
|
||
|
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
|
||
|
|
||
|
[OutputEndpoint("data")]
|
||
|
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
|
||
|
|
||
|
[Endpoint]
|
||
|
public readonly TRef<DirectoryServiceContract.Imp:Start> nsRef;
|
||
|
|
||
|
[StringParameter("filename", Mandatory = true, Position = 0, HelpMessage = "Name of file to create")]
|
||
|
internal string fileName;
|
||
|
|
||
|
[StringParameter("c", Default = null, Mandatory = false, HelpMessage = "Initial contents of file as a text string")]
|
||
|
internal string contentsString;
|
||
|
|
||
|
[StringParameter("x", Default = null, Mandatory = false, HelpMessage = "Initial contents of file as a sequence of hexadecimal bytes, such as 000FA8")]
|
||
|
internal string contentsHexString;
|
||
|
|
||
|
[LongParameter("s", Default = 0, Mandatory = false,
|
||
|
HelpMessage = "Size of file. Specified contents will be repeated to fill it, or all zero bits will be used if no pattern is specified.")]
|
||
|
internal long fileSize;
|
||
|
|
||
|
reflective internal Parameters();
|
||
|
|
||
|
internal int AppMain() {
|
||
|
return FsCreateFile.AppMain(this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class FsCreateFile
|
||
|
{
|
||
|
internal static bool CreateFile(string! fileName, DirectoryServiceContract.Imp! ds)
|
||
|
{
|
||
|
ErrorCode error;
|
||
|
FileUtils.CreateFile(fileName, ds, out error);
|
||
|
bool ok = (error == ErrorCode.NoError);
|
||
|
if (!ok) {
|
||
|
Console.WriteLine(" File ({0}) create failed. reason:{1}",
|
||
|
fileName, SdsUtils.ErrorCodeToString(error) );
|
||
|
}
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
internal static bool WriteToFile(string! fileName, byte[]! data, long size)
|
||
|
{
|
||
|
if (size == 0) return true;
|
||
|
|
||
|
ErrorCode error;
|
||
|
FileContract.Imp:Ready fileClient = null;
|
||
|
try {
|
||
|
fileClient = FileUtils.OpenFile(fileName, out error);
|
||
|
if (error != ErrorCode.NoError) {
|
||
|
Console.WriteLine(" File ({0}) open failed. reason:{1}",
|
||
|
fileName, SdsUtils.ErrorCodeToString(error) );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
long i;
|
||
|
for (i=0; i < size/data.Length; i++) {
|
||
|
FileUtils.Write((!)fileClient, data.Length * i, data);
|
||
|
}
|
||
|
if ((size % data.Length) > 0) {
|
||
|
FileUtils.Write((!)fileClient, 0, (int)(size % data.Length), data.Length * i, data);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
finally {
|
||
|
delete fileClient;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static byte HexUpperCharToByte(char hexChar)
|
||
|
{
|
||
|
if (Char.IsDigit(hexChar)) {
|
||
|
return (byte)(int.Parse(new String(hexChar, 1)));
|
||
|
}
|
||
|
else {
|
||
|
switch(hexChar) {
|
||
|
case 'A': return 10;
|
||
|
case 'B': return 11;
|
||
|
case 'C': return 12;
|
||
|
case 'D': return 13;
|
||
|
case 'E': return 14;
|
||
|
case 'F': return 15;
|
||
|
}
|
||
|
throw new FormatException(String.Format("Invalid hex character '{0}'", hexChar));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static byte[]! HexStringToBytes(string! hex)
|
||
|
{
|
||
|
foreach (char c in " \t\r\n") {
|
||
|
hex = hex.Replace(new String(c,1), "");
|
||
|
}
|
||
|
hex = hex.ToUpper();
|
||
|
if (hex.Length == 0) {
|
||
|
throw new FormatException("Hex byte string should not be empty.");
|
||
|
}
|
||
|
if ((hex.Length % 2) != 0) {
|
||
|
throw new FormatException("Hex byte string should contain an even number of digits.");
|
||
|
}
|
||
|
|
||
|
byte[]! result = new byte[hex.Length / 2];
|
||
|
for(int i=0; i < result.Length; i++) {
|
||
|
result[i] = (byte)(HexUpperCharToByte(hex[2*i]) * 16 +
|
||
|
HexUpperCharToByte(hex[2*i + 1]));
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
internal static int AppMain(Parameters! config)
|
||
|
{
|
||
|
if (config.contentsString != null && config.contentsHexString != null) {
|
||
|
Console.WriteLine("Can only specify at most one of the options -c or -x.");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
DirectoryServiceContract.Imp ds = config.nsRef.Acquire();
|
||
|
if (ds == null) {
|
||
|
Console.WriteLine("Unable to acquire handle to the Directory Service root");
|
||
|
return -1;
|
||
|
}
|
||
|
ds.RecvSuccess();
|
||
|
|
||
|
// Check if the file already exists
|
||
|
ErrorCode error;
|
||
|
long length;
|
||
|
NodeType nodeType;
|
||
|
SdsUtils.GetAttributes((!)config.fileName, ds, out length, out nodeType, out error);
|
||
|
if (error != ErrorCode.NotFound) {
|
||
|
Console.WriteLine("Cannot create file. File already exists.");
|
||
|
delete ds;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
byte[]! data = new byte[0];
|
||
|
if (config.contentsString != null) {
|
||
|
data = Encoding.UTF8.GetBytes(config.contentsString);
|
||
|
}
|
||
|
else if (config.contentsHexString != null) {
|
||
|
data = HexStringToBytes(config.contentsHexString);
|
||
|
}
|
||
|
|
||
|
long fileSize = config.fileSize;
|
||
|
|
||
|
if (fileSize > 0 && data.Length == 0) {
|
||
|
// Fill in with zero bits
|
||
|
data = new byte[1];
|
||
|
data[0] = 0;
|
||
|
}
|
||
|
|
||
|
if (!CreateFile(config.fileName, ds)) {
|
||
|
return -1;
|
||
|
}
|
||
|
if (!WriteToFile(config.fileName, data, fileSize)) {
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
catch (FormatException ex) {
|
||
|
Console.WriteLine("Invalid parameter format: " + ex.Message + ".");
|
||
|
return -1;
|
||
|
}
|
||
|
finally {
|
||
|
delete ds;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
} // class Test
|
||
|
}
|