Skip to content

Commit c1edb43

Browse files
committed
Use dual stream for os.open with O_APPEND
1 parent f971ff6 commit c1edb43

File tree

1 file changed

+11
-5
lines changed
  • Src/IronPython.Modules

1 file changed

+11
-5
lines changed

Src/IronPython.Modules/nt.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -877,8 +877,9 @@ public static object open(CodeContext/*!*/ context, [NotNone] string path, int f
877877
FileMode fileMode = FileModeFromFlags(flags);
878878
FileAccess access = FileAccessFromFlags(flags);
879879
FileOptions options = FileOptionsFromFlags(flags);
880-
Stream s;
881-
FileStream? fs;
880+
Stream s; // the stream opened to acces the file
881+
FileStream? fs; // downcast of s if s is FileStream (this is always the case on POSIX)
882+
Stream? rs = null; // secondary read stream if needed, otherwise same as s
882883
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && IsNulFile(path)) {
883884
fs = null;
884885
s = Stream.Null;
@@ -889,15 +890,20 @@ public static object open(CodeContext/*!*/ context, [NotNone] string path, int f
889890
fs.Close();
890891
s = fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, DefaultBufferSize, options);
891892
} else if (access == FileAccess.ReadWrite && fileMode == FileMode.Append) {
893+
// .NET doesn't allow Append w/ access != Write, so open the file w/ Write
894+
// and a secondary stream w/ Read, then seek to the end.
892895
s = fs = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite, DefaultBufferSize, options);
896+
rs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, DefaultBufferSize, options);
897+
rs.Seek(0L, SeekOrigin.End);
893898
} else {
894899
s = fs = new FileStream(path, fileMode, access, FileShare.ReadWrite, DefaultBufferSize, options);
895900
}
901+
rs ??= s;
896902

897-
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
898-
return context.LanguageContext.FileManager.Add(new(s));
903+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
904+
return context.LanguageContext.FileManager.Add(fs!.SafeFileHandle.DangerousGetHandle().ToInt32(), new(rs, s));
899905
} else {
900-
return context.LanguageContext.FileManager.Add((int)fs!.SafeFileHandle.DangerousGetHandle(), new(s));
906+
return context.LanguageContext.FileManager.Add(new(rs, s));
901907
}
902908
} catch (Exception e) {
903909
throw ToPythonException(e, path);

0 commit comments

Comments
 (0)