singrdk/base/Applications/utilities/createfile/createfile.sg

252 lines
9.1 KiB
Plaintext
Raw Permalink Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Note:
//
2008-11-17 18:29:00 -05:00
using FileSystem.Utils;
2008-03-05 09:52:00 -05:00
using Microsoft.Contracts;
using Microsoft.SingSharp.Reflection;
using Microsoft.Singularity.Applications;
2008-11-17 18:29:00 -05:00
using Microsoft.Singularity.Channels;
2008-03-05 09:52:00 -05:00
using Microsoft.Singularity.Configuration;
2008-11-17 18:29:00 -05:00
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.FileSystem;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.V1.Services;
using Microsoft.Singularity;
using System.Text;
using System.Threading;
using System;
2008-03-05 09:52:00 -05:00
[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;
2008-11-17 18:29:00 -05:00
[StringParameter("filename", Mandatory=true, Position=0, HelpMessage="Name of file to create")]
2008-03-05 09:52:00 -05:00
internal string fileName;
2008-11-17 18:29:00 -05:00
[ BoolParameter("o", Default = false, Mandatory = false, HelpMessage = "Overwrite existing file") ]
internal bool overwrite;
[StringParameter("c", Default=null, Mandatory=false, HelpMessage="Initial contents of file as a text string")]
2008-03-05 09:52:00 -05:00
internal string contentsString;
2008-11-17 18:29:00 -05:00
[StringParameter("x", Default=null, Mandatory=false, HelpMessage="Initial contents of file as a sequence of hexadecimal bytes, such as 000FA8")]
2008-03-05 09:52:00 -05:00
internal string contentsHexString;
2008-11-17 18:29:00 -05:00
[StringParameter("s", Default=null, 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 string fileSize;
2008-03-05 09:52:00 -05:00
reflective internal Parameters();
internal int AppMain() {
return FsCreateFile.AppMain(this);
}
}
public class FsCreateFile
{
2008-11-17 18:29:00 -05:00
private const int WriteChunkBytes = 128 * 1024;
2008-03-05 09:52:00 -05:00
internal static bool CreateFile(string! fileName, DirectoryServiceContract.Imp! ds)
{
ErrorCode error;
FileUtils.CreateFile(fileName, ds, out error);
bool ok = (error == ErrorCode.NoError);
if (!ok) {
2008-11-17 18:29:00 -05:00
Console.WriteLine("File ({0}) create failed. Reason: {1}",
fileName, SdsUtils.ErrorCodeToString(error));
2008-03-05 09:52:00 -05:00
}
return ok;
}
2008-11-17 18:29:00 -05:00
private static bool
WritePattern(FileContract.Imp! fileClient, byte[]! pattern, int size)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
// Create a buffer to write out data and fill it with
// repeated copies of pattern.
int writeBufferBytes = size;
if (writeBufferBytes > WriteChunkBytes) {
writeBufferBytes = WriteChunkBytes;
}
writeBufferBytes -= (writeBufferBytes % pattern.Length);
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
byte []! writeBuffer = new byte[writeBufferBytes];
for (int i = 0; i < writeBuffer.Length; i += pattern.Length) {
Array.Copy(pattern, 0, writeBuffer, i, pattern.Length);
}
int end = size - (size % pattern.Length);
for (int i = 0; i < end; i += writeBuffer.Length) {
if (FileUtils.Write(fileClient, i, writeBuffer) !=
writeBuffer.Length) {
Console.WriteLine("Truncated write.");
return false;
}
}
if (end != size &&
FileUtils.Write((!)fileClient, 0, (int)(size - end), end,
writeBuffer) != (size - end)) {
Console.WriteLine("Truncated write.");
return false;
}
return true;
}
internal static bool
WriteToFile(string! fileName, byte[]! pattern, int size)
{
2008-03-05 09:52:00 -05:00
FileContract.Imp:Ready fileClient = null;
try {
2008-11-17 18:29:00 -05:00
ErrorCode error;
2008-03-05 09:52:00 -05:00
fileClient = FileUtils.OpenFile(fileName, out error);
2008-11-17 18:29:00 -05:00
if (fileClient != null) {
assert error == ErrorCode.NoError;
return WritePattern(fileClient, pattern, (int)size);
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
return false;
2008-03-05 09:52:00 -05:00
}
finally {
delete fileClient;
}
}
private static byte HexUpperCharToByte(char hexChar)
{
if (Char.IsDigit(hexChar)) {
return (byte)(int.Parse(new String(hexChar, 1)));
}
else {
2008-11-17 18:29:00 -05:00
switch (hexChar) {
2008-03-05 09:52:00 -05:00
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];
2008-11-17 18:29:00 -05:00
for (int i = 0; i < result.Length; i++) {
2008-03-05 09:52:00 -05:00
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;
2008-11-17 18:29:00 -05:00
FileAttributesRecord fileAttributes;
SdsUtils.GetAttributes((!)config.fileName, ds, out fileAttributes, out error);
if (config.overwrite) {
if (error == ErrorCode.NotFound) {
Console.WriteLine("Cannot overwrite file. File does not exist.");
delete ds;
return -1;
}
}
else if (error != ErrorCode.NotFound) {
2008-03-05 09:52:00 -05:00
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);
}
2008-11-17 18:29:00 -05:00
int fileSize = 0;
if (config.fileSize != null) {
ulong userFileSize = DiskSizeUtils.ParsePrettySizeString(config.fileSize);
if (userFileSize > (ulong)Int32.MaxValue) {
Console.WriteLine("File size not supported.");
return -1;
}
fileSize = (int)userFileSize;
}
else {
fileSize = data.Length;
}
2008-03-05 09:52:00 -05:00
if (fileSize > 0 && data.Length == 0) {
// Fill in with zero bits
data = new byte[1];
data[0] = 0;
}
2008-11-17 18:29:00 -05:00
if (config.overwrite == false &&
!CreateFile(config.fileName, ds)) {
2008-03-05 09:52:00 -05:00
return -1;
}
2008-11-17 18:29:00 -05:00
if (fileSize != 0 &&
!WriteToFile(config.fileName, data, fileSize)) {
2008-03-05 09:52:00 -05:00
return -1;
}
}
catch (FormatException ex) {
Console.WriteLine("Invalid parameter format: " + ex.Message + ".");
return -1;
}
finally {
delete ds;
}
return 0;
}
} // class Test
}