private static Interop.Sys.OpenFlags PreOpenConfigurationFromOptions(FileMode mode, FileAccess access, FileOptions options)
{
// Translate FileMode. Most of the values map cleanly to one or more options for open.
Interop.Sys.OpenFlags flags = default(Interop.Sys.OpenFlags);
switch (mode)
{
default:
case FileMode.Open: // Open maps to the default behavior for open(...). No flags needed.
break;
case FileMode.Append: // Append is the same as OpenOrCreate, except that we'll also separately jump to the end later
case FileMode.OpenOrCreate:
flags |= Interop.Sys.OpenFlags.O_CREAT;
break;
case FileMode.Create:
flags |= (Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_TRUNC);
break;
case FileMode.CreateNew:
flags |= (Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_EXCL);
break;
case FileMode.Truncate:
flags |= Interop.Sys.OpenFlags.O_TRUNC;
break;
}
// Translate FileAccess. All possible values map cleanly to corresponding values for open.
switch (access)
{
case FileAccess.Read:
flags |= Interop.Sys.OpenFlags.O_RDONLY;
break;
case FileAccess.ReadWrite:
flags |= Interop.Sys.OpenFlags.O_RDWR;
break;
case FileAccess.Write:
flags |= Interop.Sys.OpenFlags.O_WRONLY;
break;
}
// Translate some FileOptions; some just aren't supported, and others will be handled after calling open.
// - Asynchronous: Handled in ctor, setting _useAsync and SafeFileHandle.IsAsync to true
// - DeleteOnClose: Doesn't have a Unix equivalent, but we approximate it in Dispose
// - Encrypted: No equivalent on Unix and is ignored
// - RandomAccess: Implemented after open if posix_fadvise is available
// - SequentialScan: Implemented after open if posix_fadvise is available
// - WriteThrough: Handled here
if ((options & FileOptions.WriteThrough) != 0)
{
flags |= Interop.Sys.OpenFlags.O_SYNC;
}
return flags;
}