public override void Execute(SharedObjects shared) { string pathString = PopValueAssert(shared, true).ToString(); string toAppend = PopValueAssert(shared).ToString(); AssertArgBottomAndConsume(shared); if (shared.VolumeMgr != null) { GlobalPath path = shared.VolumeMgr.GlobalPathFromObject(pathString); Volume volume = shared.VolumeMgr.GetVolumeFromPath(path); VolumeItem volumeItem = volume.Open(path) as VolumeFile; VolumeFile volumeFile = null; if (volumeItem == null) { volumeFile = volume.CreateFile(path); } else if (volumeItem is VolumeDirectory) { throw new KOSFileException("Can't append to file: path points to a directory"); } else { volumeFile = volumeItem as VolumeFile; } if (!volumeFile.WriteLn(toAppend)) { throw new KOSFileException("Can't append to file: not enough space or access forbidden"); } } }
public override void Execute(SharedObjects shared) { string fileName = PopValueAssert(shared, true).ToString(); string expressionResult = PopValueAssert(shared).ToString(); AssertArgBottomAndConsume(shared); if (shared.VolumeMgr != null) { Volume volume = shared.VolumeMgr.CurrentVolume; if (volume != null) { VolumeFile volumeFile = volume.OpenOrCreate(fileName); if (volumeFile == null || !volumeFile.WriteLn(expressionResult)) { throw new KOSFileException("Can't append to file: not enough space or access forbidden"); } } else { throw new KOSFileException("Volume not found"); } } }
public override void ThreadFinish() { switch (compileMode) { case CompileMode.RUN: programContext.AddParts(codeParts); shared.Cpu.StopCompileStopwatch(); break; case CompileMode.LOAD: int programAddress = programContext.AddObjectParts(codeParts, path.ToString()); // push the entry point address of the new program onto the stack shared.Cpu.PushStack(programAddress); shared.Cpu.PushStack(BooleanValue.False); break; case CompileMode.FILE: VolumeFile written = volume.SaveFile(outPath, new FileContent(codeParts)); if (written == null) { throw new KOSFileException("Can't save compiled file: not enough space or access forbidden"); } break; default: break; } }
public void CanReadAndWriteFiles() { string dir = "/content_parent/content_test"; string content = "some test content!@#$;\n\rtaenstałąż"; int contentLength = Encoding.UTF8.GetBytes(content).Length; VolumeFile volumeFile = TestVolume.CreateFile(VolumePath.FromString(dir)); Assert.AreEqual(0, volumeFile.ReadAll().Bytes.Length); Assert.AreEqual("", volumeFile.ReadAll().String); Assert.IsTrue(volumeFile.Write(content)); Assert.AreEqual(FileCategory.ASCII, volumeFile.ReadAll().Category); Assert.AreEqual(contentLength, TestVolume.Size); if (ExpectedCapacity != Volume.INFINITE_CAPACITY) { Assert.AreEqual(ExpectedCapacity - contentLength, TestVolume.FreeSpace); } else { Assert.AreEqual(Volume.INFINITE_CAPACITY, TestVolume.FreeSpace); } Assert.AreEqual(contentLength, volumeFile.Size); Assert.AreEqual(content, volumeFile.ReadAll().String); // we should be able to save the same file again Assert.IsTrue(TestVolume.SaveFile(volumeFile) != null); }
public override void Execute(SharedObjects shared) { string fileName = PopValueAssert(shared, true).ToString(); AssertArgBottomAndConsume(shared); VolumeFile volumeFile = shared.VolumeMgr.CurrentVolume.Create(fileName); ReturnValue = volumeFile; }
public void CanCopyFileToRootDirectory() { GlobalPath targetPath = GlobalPath.FromString("1:"); Assert.IsTrue(volumeManager.Copy(subsubdir1File1Path, targetPath)); Assert.AreEqual(1, TargetVolume.Root.List().Count); VolumeFile file = (TargetVolume.Open(file1) as VolumeFile); Assert.AreEqual("subsubdir1File1\n", file.ReadAll().String); }
public override void Execute(SharedObjects shared) { object volumeId = PopValueAssert(shared, true); string direction = PopValueAssert(shared).ToString(); string fileName = PopValueAssert(shared, true).ToString(); AssertArgBottomAndConsume(shared); SafeHouse.Logger.Log(string.Format("FunctionCopy: Volume: {0} Direction: {1} Filename: {2}", volumeId, direction, fileName)); if (shared.VolumeMgr != null) { Volume origin; Volume destination; if (direction == "from") { origin = volumeId is Volume ? volumeId as Volume : shared.VolumeMgr.GetVolume(volumeId); destination = shared.VolumeMgr.CurrentVolume; } else { origin = shared.VolumeMgr.CurrentVolume; destination = volumeId is Volume ? volumeId as Volume : shared.VolumeMgr.GetVolume(volumeId); } if (origin != null && destination != null) { if (origin == destination) { throw new Exception("Cannot copy from a volume to the same volume."); } VolumeFile file = origin.Open(fileName); if (file != null) { if (destination.Save(file.Name, file.ReadAll()) == null) { throw new Exception("File copy failed"); } } else { throw new Exception(string.Format("File '{0}' not found", fileName)); } } else { throw new Exception(string.Format("Volume {0} not found", volumeId)); } } }
public override void Execute(SafeSharedObjects shared) { object pathObject = PopValueAssert(shared, true); AssertArgBottomAndConsume(shared); GlobalPath path = shared.VolumeMgr.GlobalPathFromObject(pathObject); Volume volume = shared.VolumeMgr.GetVolumeFromPath(path); VolumeFile volumeFile = volume.CreateFile(path); ReturnValue = volumeFile; }
public override void Execute(SharedObjects shared) { string fileName = PopValueAssert(shared, true).ToString(); AssertArgBottomAndConsume(shared); VolumeFile volumeFile = shared.VolumeMgr.CurrentVolume.Open(fileName); if (volumeFile == null) { throw new KOSException("File does not exist: " + fileName); } ReturnValue = volumeFile; }
protected static void DelegateLoadContents(KOSTextEditPopup me) { me.volume = me.loadingVolume; me.fileName = me.loadingFileName; VolumeFile file = me.volume.Open(me.fileName); if (file == null) { me.term.Print("[New File]"); me.contents = ""; } else { me.contents = file.ReadAll().String; } me.isDirty = false; }
private string GetSourceLine(GlobalPath path, int line) { string returnVal = "(Can't show source line)"; if (line < 0) { // Special exception - if line number is negative then this isn't from any // line of user's code but from the system itself (like the triggers the compiler builds // to recalculate LOCK THROTTLE and LOCK STEERING each time there's an Update). return("<<System Built-In Flight Control Updater>>"); } if (path is InternalPath) { return((path as InternalPath).Line(line)); } Volume vol; try { vol = Shared.VolumeMgr.GetVolumeFromPath(path); } catch (KOSPersistenceException) { return(returnVal); } VolumeFile file = vol.Open(path) as VolumeFile; if (file != null) { if (file.ReadAll().Category == FileCategory.KSM) { return("<<machine language file: can't show source line>>"); } string[] splitLines = file.ReadAll().String.Split('\n'); if (splitLines.Length >= line) { returnVal = splitLines[line - 1]; } } return(returnVal); }
public override void Execute(SharedObjects shared) { string fileName = PopValueAssert(shared, true).ToString(); AssertArgBottomAndConsume(shared); VolumeFile volumeFile = shared.VolumeMgr.CurrentVolume.Open(fileName); if (volumeFile == null) { throw new KOSException("File does not exist: " + fileName); } object read = new SerializationMgr(shared).Deserialize(volumeFile.ReadAll().String, JsonFormatter.ReaderInstance); ReturnValue = read; }
public override void Execute(SafeSharedObjects shared) { object pathObject = PopValueAssert(shared, true); AssertArgBottomAndConsume(shared); GlobalPath path = shared.VolumeMgr.GlobalPathFromObject(pathObject); Volume volume = shared.VolumeMgr.GetVolumeFromPath(path); VolumeFile volumeFile = volume.Open(path) as VolumeFile; if (volumeFile == null) { throw new KOSException("File does not exist: " + path); } Structure read = new SafeSerializationMgr(shared).Deserialize(volumeFile.ReadAll().String, JsonFormatter.ReaderInstance) as SerializableStructure; ReturnValue = read; }
private void CompareDirectories(GlobalPath dir1Path, GlobalPath dir2Path) { Volume dir1Volume = volumeManager.GetVolumeFromPath(dir1Path); Volume dir2Volume = volumeManager.GetVolumeFromPath(dir2Path); VolumeDirectory dir1 = dir1Volume.Open(dir1Path) as VolumeDirectory; VolumeDirectory dir2 = dir2Volume.Open(dir2Path) as VolumeDirectory; Assert.NotNull(dir1); Assert.NotNull(dir2); int dir1Count = dir1.List().Count; int dir2Count = dir2.List().Count; if (dir1Count != dir2Count) { Assert.Fail("Item count not equal: " + dir1Count + " != " + dir2Count); } foreach (KeyValuePair <string, VolumeItem> pair in dir1.List()) { VolumeItem dir2Item = dir2Volume.Open(dir2Path.Combine(pair.Key)); if (pair.Value is VolumeDirectory && dir2Item is VolumeDirectory) { CompareDirectories(dir1Path.Combine(pair.Key), dir2Path.Combine(pair.Key)); } else if (pair.Value is VolumeFile && dir2Item is VolumeFile) { VolumeFile file1 = pair.Value as VolumeFile; VolumeFile file2 = dir2Item as VolumeFile; Assert.AreEqual(file1.ReadAll(), file2.ReadAll()); } else { Assert.Fail("Items are not of the same type: " + dir1Path.Combine(pair.Key) + ", " + dir2Path.Combine(pair.Key)); } } }
protected static void DelegateLoadContents(KOSTextEditPopup me) { VolumeItem item = me.loadingVolume.Open(me.loadingPath); if (item == null) { me.term.Print("[New File]"); me.contents = ""; } else if (item is VolumeFile) { VolumeFile file = item as VolumeFile; me.loadingPath = GlobalPath.FromVolumePath(item.Path, me.loadingPath.VolumeId); me.contents = file.ReadAll().String; } else { throw new KOSPersistenceException("Path '" + me.loadingPath + "' points to a directory"); } me.volume = me.loadingVolume; me.isDirty = false; }
/// <summary> /// Dispose of the current object /// </summary> public void Dispose() { VolumeFile?.Close(); }
public VolumeFile SaveFile(VolumeFile volumeFile) { return SaveFile(volumeFile.Path, volumeFile.ReadAll()); }
public override void Execute(SharedObjects shared) { bool defaultOutput = false; bool justCompiling = false; // is this load() happening to compile, or to run? string fileNameOut = null; object topStack = PopValueAssert(shared, true); // null if there's no output file (output file means compile, not run). if (topStack != null) { justCompiling = true; string outputArg = topStack.ToString(); if (outputArg.Equals("-default-compile-out-")) { defaultOutput = true; } else { fileNameOut = PersistenceUtilities.CookedFilename(outputArg, Volume.KOS_MACHINELANGUAGE_EXTENSION); } } string fileName = null; topStack = PopValueAssert(shared, true); if (topStack != null) { fileName = topStack.ToString(); } AssertArgBottomAndConsume(shared); if (fileName == null) { throw new KOSFileException("No filename to load was given."); } VolumeFile file = shared.VolumeMgr.CurrentVolume.Open(fileName, !justCompiling); // if running, look for KSM first. If compiling look for KS first. if (file == null) { throw new KOSFileException(string.Format("Can't find file '{0}'.", fileName)); } fileName = file.Name; // just in case GetByName picked an extension that changed it. FileContent fileContent = file.ReadAll(); // filename is now guaranteed to have an extension. To make default output name, replace the extension with KSM: if (defaultOutput) { fileNameOut = fileName.Substring(0, fileName.LastIndexOf('.')) + "." + Volume.KOS_MACHINELANGUAGE_EXTENSION; } if (fileNameOut != null && fileName == fileNameOut) { throw new KOSFileException("Input and output filenames must differ."); } if (shared.VolumeMgr == null) { return; } if (shared.VolumeMgr.CurrentVolume == null) { throw new KOSFileException("Volume not found"); } if (shared.ScriptHandler != null) { shared.Cpu.StartCompileStopwatch(); var options = new CompilerOptions { LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager }; string filePath = shared.VolumeMgr.GetVolumeRawIdentifier(shared.VolumeMgr.CurrentVolume) + "/" + fileName; // add this program to the address space of the parent program, // or to a file to save: if (justCompiling) { List <CodePart> compileParts = shared.ScriptHandler.Compile(filePath, 1, fileContent.String, string.Empty, options); VolumeFile volumeFile = shared.VolumeMgr.CurrentVolume.Save(fileNameOut, new FileContent(compileParts)); if (volumeFile == null) { throw new KOSFileException("Can't save compiled file: not enough space or access forbidden"); } } else { var programContext = ((CPU)shared.Cpu).SwitchToProgramContext(); List <CodePart> parts; if (fileContent.Category == FileCategory.KSM) { string prefix = programContext.Program.Count.ToString(); parts = fileContent.AsParts(filePath, prefix); } else { parts = shared.ScriptHandler.Compile(filePath, 1, fileContent.String, "program", options); } int programAddress = programContext.AddObjectParts(parts); // push the entry point address of the new program onto the stack shared.Cpu.PushStack(programAddress); } shared.Cpu.StopCompileStopwatch(); } }
//public abstract bool AppendToFile(string name, string textToAppend); //public abstract bool AppendToFile(string name, byte[] bytesToAppend); public VolumeFile Save(VolumeFile volumeFile) { return Save(volumeFile.Name, volumeFile.ReadAll()); }
private int FileInfoComparer(VolumeFile a, VolumeFile b) { return string.CompareOrdinal(a.Name, b.Name); }
public override void Execute(SharedObjects shared) { // run() is strange. It needs two levels of args - the args to itself, and the args it is meant to // pass on to the program it's invoking. First, these are the args to run itself: object volumeId = PopValueAssert(shared, true); string fileName = PopValueAssert(shared, true).ToString(); AssertArgBottomAndConsume(shared); // Now the args it is going to be passing on to the program: var progArgs = new List <object>(); int argc = CountRemainingArgs(shared); for (int i = 0; i < argc; ++i) { progArgs.Add(PopValueAssert(shared, true)); } AssertArgBottomAndConsume(shared); if (shared.VolumeMgr == null) { return; } if (shared.VolumeMgr.CurrentVolume == null) { throw new Exception("Volume not found"); } VolumeFile file = shared.VolumeMgr.CurrentVolume.Open(fileName, true); if (file == null) { throw new Exception(string.Format("File '{0}' not found", fileName)); } if (shared.ScriptHandler == null) { return; } if (volumeId != null) { Volume targetVolume = shared.VolumeMgr.GetVolume(volumeId); if (targetVolume != null) { if (shared.ProcessorMgr != null) { string filePath = string.Format("{0}/{1}", shared.VolumeMgr.GetVolumeRawIdentifier(targetVolume), fileName); var options = new CompilerOptions { LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager }; List <CodePart> parts = shared.ScriptHandler.Compile(filePath, 1, file.ReadAll().String, "program", options); var builder = new ProgramBuilder(); builder.AddRange(parts); List <Opcode> program = builder.BuildProgram(); shared.ProcessorMgr.RunProgramOn(program, targetVolume); } } else { throw new KOSFileException("Volume not found"); } } else { // clear the "program" compilation context shared.Cpu.StartCompileStopwatch(); shared.ScriptHandler.ClearContext("program"); string filePath = shared.VolumeMgr.GetVolumeRawIdentifier(shared.VolumeMgr.CurrentVolume) + "/" + fileName; var options = new CompilerOptions { LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager }; var programContext = ((CPU)shared.Cpu).SwitchToProgramContext(); List <CodePart> codeParts; FileContent content = file.ReadAll(); if (content.Category == FileCategory.KSM) { string prefix = programContext.Program.Count.ToString(); codeParts = content.AsParts(fileName, prefix); } else { try { codeParts = shared.ScriptHandler.Compile(filePath, 1, content.String, "program", options); } catch (Exception) { // If it died due to a compile error, then we won't really be able to switch to program context // as was implied by calling Cpu.SwitchToProgramContext() up above. The CPU needs to be // told that it's still in interpreter context, or else it fails to advance the interpreter's // instruction pointer and it will just try the "call run()" instruction again: shared.Cpu.BreakExecution(false); throw; } } programContext.AddParts(codeParts); shared.Cpu.StopCompileStopwatch(); } // Because run() returns FIRST, and THEN the CPU jumps to the new program's first instruction that it set up, // it needs to put the return stack in a weird order. Its return value needs to be buried UNDER the args to the // program it's calling: UsesAutoReturn = false; shared.Cpu.PushStack(0); // dummy return that all functions have. // Put the args for the program being called back on in the same order they were in before (so read the list backward): shared.Cpu.PushStack(new KOSArgMarkerType()); for (int i = argc - 1; i >= 0; --i) { shared.Cpu.PushStack(progArgs[i]); } }
private string GetSourceLine(string filePath, int line) { string returnVal = "(Can't show source line)"; if (line < 0 && string.IsNullOrEmpty(filePath)) { // Special exception - if line number is negative then this isn't from any // line of user's code but from the system itself (like the triggers the compiler builds // to recalculate LOCK THROTTLE and LOCK STEERING each time there's an Update). return("<<System Built-In Flight Control Updater>>"); } if (string.IsNullOrEmpty(filePath)) { return("<<Probably internal error within kOS C# code>>"); } string[] pathParts = filePath.Split('/'); string fileName = pathParts.Last(); Volume vol; if (pathParts.Length > 1) { string volName = pathParts.First(); if (Regex.IsMatch(volName, @"^\d+$")) { // If the volume is a number, then get the volume by integer id. int volNum; int.TryParse(volName, out volNum); vol = Shared.VolumeMgr.GetVolume(volNum); } else { // If the volume is not a number, then get the volume by name string. vol = Shared.VolumeMgr.GetVolume(volName); } } else { vol = Shared.VolumeMgr.CurrentVolume; } if (fileName == "interpreter history") { return(Shared.Interpreter.GetCommandHistoryAbsolute(line)); } VolumeFile file = vol.Open(fileName); if (file != null) { if (file.ReadAll().Category == FileCategory.KSM) { return("<<machine language file: can't show source line>>"); } string[] splitLines = file.ReadAll().String.Split('\n'); if (splitLines.Length >= line) { returnVal = splitLines[line - 1]; } } return(returnVal); }
protected bool CopyFileToDirectory(VolumeFile volumeFile, VolumeDirectory volumeDirectory, bool verifyFreeSpace) { return volumeDirectory.Volume.SaveFile(volumeDirectory.Path.Combine(volumeFile.Name), volumeFile.ReadAll(), verifyFreeSpace) != null; }
protected bool CopyFile(VolumeFile volumeFile, GlobalPath destinationPath, Volume targetVolume, bool verifyFreeSpace) { return targetVolume.SaveFile(destinationPath, volumeFile.ReadAll(), verifyFreeSpace) != null; }
public override void Execute(SharedObjects shared) { // run() is strange. It needs two levels of args - the args to itself, and the args it is meant to // pass on to the program it's invoking. First, these are the args to run itself: object volumeId = PopValueAssert(shared, true); object pathObject = PopValueAssert(shared, true); AssertArgBottomAndConsume(shared); // Now the args it is going to be passing on to the program: var progArgs = new List <object>(); int argc = CountRemainingArgs(shared); for (int i = 0; i < argc; ++i) { progArgs.Add(PopValueAssert(shared, true)); } AssertArgBottomAndConsume(shared); if (shared.VolumeMgr == null) { return; } GlobalPath path = shared.VolumeMgr.GlobalPathFromObject(pathObject); Volume volume = shared.VolumeMgr.GetVolumeFromPath(path); VolumeFile volumeFile = volume.Open(path) as VolumeFile; FileContent content = volumeFile != null?volumeFile.ReadAll() : null; if (content == null) { throw new Exception(string.Format("File '{0}' not found", path)); } if (shared.ScriptHandler == null) { return; } if (volumeId != null) { throw new KOSObsoletionException("v1.0.2", "run [file] on [volume]", "None", ""); } else { // clear the "program" compilation context shared.Cpu.StartCompileStopwatch(); shared.ScriptHandler.ClearContext("program"); //string filePath = shared.VolumeMgr.GetVolumeRawIdentifier(shared.VolumeMgr.CurrentVolume) + "/" + fileName; var options = new CompilerOptions { LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager }; var programContext = shared.Cpu.SwitchToProgramContext(); List <CodePart> codeParts; if (content.Category == FileCategory.KSM) { string prefix = programContext.Program.Count.ToString(); codeParts = content.AsParts(path, prefix); programContext.AddParts(codeParts); shared.Cpu.StopCompileStopwatch(); } else { shared.Cpu.YieldProgram(YieldFinishedCompile.RunScript(path, 1, content.String, "program", options)); } } // Because run() returns FIRST, and THEN the CPU jumps to the new program's first instruction that it set up, // it needs to put the return stack in a weird order. Its return value needs to be buried UNDER the args to the // program it's calling: UsesAutoReturn = false; shared.Cpu.PushStack(0); // dummy return that all functions have. // Put the args for the program being called back on in the same order they were in before (so read the list backward): shared.Cpu.PushStack(new KOSArgMarkerType()); for (int i = argc - 1; i >= 0; --i) { shared.Cpu.PushStack(progArgs[i]); } }
public override void Execute(SharedObjects shared) { // NOTE: The built-in load() function actually ends up returning // two things on the stack: on top is a boolean for whether the program // was already loaded, and under that is an integer for where to jump to // to call it. The load() function is NOT meant to be called directly from // a user script. // (unless it's being called in compile-only mode, in which case it // returns the default dummy zero on the stack like everything else does). bool defaultOutput = false; bool justCompiling = false; // is this load() happening to compile, or to run? GlobalPath outPath = null; object topStack = PopValueAssert(shared, true); // null if there's no output file (output file means compile, not run). if (topStack != null) { justCompiling = true; string outputArg = topStack.ToString(); if (outputArg.Equals("-default-compile-out-")) { defaultOutput = true; } else { outPath = shared.VolumeMgr.GlobalPathFromObject(outputArg); } } object skipAlreadyObject = PopValueAssert(shared, false); bool skipIfAlreadyCompiled = (skipAlreadyObject is bool) ? (bool)skipAlreadyObject : false; object pathObject = PopValueAssert(shared, true); AssertArgBottomAndConsume(shared); if (pathObject == null) { throw new KOSFileException("No filename to load was given."); } GlobalPath path = shared.VolumeMgr.GlobalPathFromObject(pathObject); Volume volume = shared.VolumeMgr.GetVolumeFromPath(path); VolumeFile file = volume.Open(path, !justCompiling) as VolumeFile; // if running, look for KSM first. If compiling look for KS first. if (file == null) { throw new KOSFileException(string.Format("Can't find file '{0}'.", path)); } path = GlobalPath.FromVolumePath(file.Path, shared.VolumeMgr.GetVolumeId(volume)); if (skipIfAlreadyCompiled && !justCompiling) { var programContext = ((CPU)shared.Cpu).SwitchToProgramContext(); int programAddress = programContext.GetAlreadyCompiledEntryPoint(path.ToString()); if (programAddress >= 0) { // TODO - The check could also have some dependancy on whether the file content changed on // disk since last time, but that would also mean having to have a way to clear out the old // copy of the compiled file from the program context, which right now doesn't exist. (Without // that, doing something like a loop that re-wrote a file and re-ran it 100 times would leave // 100 old dead copies of the compiled opcodes in memory, only the lastmost copy being really used.) // We're done here. Skip the compile. Point the caller at the already-compiled version. shared.Cpu.PushStack(programAddress); this.ReturnValue = true; // tell caller that it already existed. return; } } FileContent fileContent = file.ReadAll(); // filename is now guaranteed to have an extension. To make default output name, replace the extension with KSM: if (defaultOutput) { outPath = path.ChangeExtension(Volume.KOS_MACHINELANGUAGE_EXTENSION); } if (path.Equals(outPath)) { throw new KOSFileException("Input and output paths must differ."); } if (shared.VolumeMgr == null) { return; } if (shared.VolumeMgr.CurrentVolume == null) { throw new KOSFileException("Volume not found"); } if (shared.ScriptHandler != null) { shared.Cpu.StartCompileStopwatch(); var options = new CompilerOptions { LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager }; // add this program to the address space of the parent program, // or to a file to save: if (justCompiling) { // since we've already read the file content, use the volume from outPath instead of the source path volume = shared.VolumeMgr.GetVolumeFromPath(outPath); List <CodePart> compileParts = shared.ScriptHandler.Compile(path, 1, fileContent.String, string.Empty, options); VolumeFile written = volume.SaveFile(outPath, new FileContent(compileParts)); if (written == null) { throw new KOSFileException("Can't save compiled file: not enough space or access forbidden"); } } else { var programContext = ((CPU)shared.Cpu).SwitchToProgramContext(); List <CodePart> parts; if (fileContent.Category == FileCategory.KSM) { string prefix = programContext.Program.Count.ToString(); parts = fileContent.AsParts(path, prefix); } else { parts = shared.ScriptHandler.Compile(path, 1, fileContent.String, "program", options); } int programAddress = programContext.AddObjectParts(parts, path.ToString()); // push the entry point address of the new program onto the stack shared.Cpu.PushStack(programAddress); this.ReturnValue = false; // did not already exist. } shared.Cpu.StopCompileStopwatch(); } }