Merge pull request #6657 from Bond-009/dotnetbug

This commit is contained in:
Claus Vium 2021-10-09 12:19:44 +02:00 committed by GitHub
commit 1156699481
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 77 additions and 74 deletions

View File

@ -359,14 +359,17 @@ namespace Emby.Dlna
// The stream should exist as we just got its name from GetManifestResourceNames
using (var stream = _assembly.GetManifestResourceStream(name)!)
{
var length = stream.Length;
var fileInfo = _fileSystem.GetFileInfo(path);
if (!fileInfo.Exists || fileInfo.Length != stream.Length)
if (!fileInfo.Exists || fileInfo.Length != length)
{
Directory.CreateDirectory(systemProfilesPath);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
var fileOptions = AsyncFile.WriteOptions;
fileOptions.Mode = FileMode.CreateNew;
fileOptions.PreallocationSize = length;
using (var fileStream = new FileStream(path, fileOptions))
{
await stream.CopyToAsync(fileStream).ConfigureAwait(false);
}

View File

@ -102,7 +102,7 @@ namespace Emby.Drawing
{
var file = await ProcessImage(options).ConfigureAwait(false);
using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
using (var fileStream = AsyncFile.OpenRead(file.Item1))
{
await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
}

View File

@ -41,20 +41,19 @@ namespace Emby.Server.Implementations.AppBase
xmlSerializer.SerializeToStream(configuration, stream);
// Take the object we just got and serialize it back to bytes
byte[] newBytes = stream.GetBuffer();
int newBytesLen = (int)stream.Length;
Span<byte> newBytes = stream.GetBuffer().AsSpan(0, (int)stream.Length);
// If the file didn't exist before, or if something has changed, re-save
if (buffer == null || !newBytes.AsSpan(0, newBytesLen).SequenceEqual(buffer))
if (buffer == null || !newBytes.SequenceEqual(buffer))
{
var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path));
Directory.CreateDirectory(directory);
// Save it after load in case we got new items
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
{
fs.Write(newBytes, 0, newBytesLen);
fs.Write(newBytes);
}
}

View File

@ -46,8 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
using (var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
{
onStarted();
@ -79,8 +78,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous);
await using var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.CopyToBufferSize, FileOptions.Asynchronous);
onStarted();

View File

@ -1848,14 +1848,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return;
}
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None))
using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
var settings = new XmlWriterSettings
{
Indent = true,
Encoding = Encoding.UTF8,
CloseOutput = false
Encoding = Encoding.UTF8
};
using (var writer = XmlWriter.Create(stream, settings))
@ -1913,14 +1911,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return;
}
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None))
using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
var settings = new XmlWriterSettings
{
Indent = true,
Encoding = Encoding.UTF8,
CloseOutput = false
Encoding = Encoding.UTF8
};
var options = _config.GetNfoConfiguration();

View File

@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
_logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
_logFileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false);
await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false);

View File

@ -183,36 +183,5 @@ namespace Jellyfin.Api.Controllers
{
return Path.Combine(_applicationPaths.CachePath, "remote-images", filename.Substring(0, 1), filename);
}
/// <summary>
/// Downloads the image.
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="urlHash">The URL hash.</param>
/// <param name="pointerCachePath">The pointer cache path.</param>
/// <returns>Task.</returns>
private async Task DownloadImage(Uri url, Guid urlHash, string pointerCachePath)
{
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
using var response = await httpClient.GetAsync(url).ConfigureAwait(false);
if (response.Content.Headers.ContentType?.MediaType == null)
{
throw new ResourceNotFoundException(nameof(response.Content.Headers.ContentType));
}
var ext = response.Content.Headers.ContentType.MediaType.AsSpan().RightPart('/').ToString();
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid.");
Directory.CreateDirectory(fullCacheDirectory);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
await response.Content.CopyToAsync(fileStream).ConfigureAwait(false);
var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath));
Directory.CreateDirectory(pointerCacheDirectory);
await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath, CancellationToken.None)
.ConfigureAwait(false);
}
}
}

View File

@ -113,11 +113,19 @@ namespace MediaBrowser.LocalMetadata.Savers
{
var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path));
Directory.CreateDirectory(directory);
// On Windows, savint the file will fail if the file is hidden or readonly
FileSystem.SetAttributes(path, false, false);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
var fileStreamOptions = new FileStreamOptions()
{
Mode = FileMode.Create,
Access = FileAccess.Write,
Share = FileShare.None,
PreallocationSize = stream.Length
};
using (var filestream = new FileStream(path, fileStreamOptions))
{
stream.CopyTo(filestream);
}

View File

@ -679,7 +679,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles
if (!string.Equals(text, newText, StringComparison.Ordinal))
{
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
using (var writer = new StreamWriter(fileStream, encoding))
{

View File

@ -7,6 +7,25 @@ namespace MediaBrowser.Model.IO
/// </summary>
public static class AsyncFile
{
/// <summary>
/// Gets the default <see cref="FileStreamOptions"/> for reading files async.
/// </summary>
public static FileStreamOptions ReadOptions => new FileStreamOptions()
{
Options = FileOptions.Asynchronous
};
/// <summary>
/// Gets the default <see cref="FileStreamOptions"/> for writing files async.
/// </summary>
public static FileStreamOptions WriteOptions => new FileStreamOptions()
{
Mode = FileMode.OpenOrCreate,
Access = FileAccess.Write,
Share = FileShare.None,
Options = FileOptions.Asynchronous
};
/// <summary>
/// Opens an existing file for reading.
/// </summary>

View File

@ -261,8 +261,10 @@ namespace MediaBrowser.Providers.Manager
_fileSystem.SetAttributes(path, false, false);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
var fileStreamOptions = AsyncFile.WriteOptions;
fileStreamOptions.Mode = FileMode.Create;
fileStreamOptions.PreallocationSize = source.Length;
await using (var fs = new FileStream(path, fileStreamOptions))
{
await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false);
}

View File

@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.Manager
{
var mimeType = MimeTypes.GetMimeType(response.Path);
var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
var stream = AsyncFile.OpenRead(response.Path);
await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false);
}

View File

@ -210,8 +210,7 @@ namespace MediaBrowser.Providers.Manager
throw new ArgumentNullException(nameof(source));
}
var fileStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var fileStream = AsyncFile.OpenRead(source);
return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken);
}

View File

@ -172,8 +172,11 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
var fileStreamOptions = AsyncFile.WriteOptions;
fileStreamOptions.Mode = FileMode.Create;
fileStreamOptions.PreallocationSize = stream.Length;
await using var xmlFileStream = new FileStream(path, fileStreamOptions);
await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
}

View File

@ -154,8 +154,10 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
Directory.CreateDirectory(Path.GetDirectoryName(path));
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
var fileStreamOptions = AsyncFile.WriteOptions;
fileStreamOptions.Mode = FileMode.Create;
fileStreamOptions.PreallocationSize = stream.Length;
await using var xmlFileStream = new FileStream(path, fileStreamOptions);
await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
}

View File

@ -172,19 +172,16 @@ namespace MediaBrowser.Providers.Studios
public IEnumerable<string> GetAvailableImages(string file)
{
using var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
using var fileStream = File.OpenRead(file);
using var reader = new StreamReader(fileStream);
var lines = new List<string>();
foreach (var line in reader.ReadAllLines())
{
if (!string.IsNullOrWhiteSpace(line))
{
lines.Add(line);
yield return line;
}
}
return lines;
}
}
}

View File

@ -244,8 +244,10 @@ namespace MediaBrowser.Providers.Subtitles
{
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, FileOptions.Asynchronous);
var fileOptions = AsyncFile.WriteOptions;
fileOptions.Mode = FileMode.CreateNew;
fileOptions.PreallocationSize = stream.Length;
using var fs = new FileStream(savePath, fileOptions);
await stream.CopyToAsync(fs).ConfigureAwait(false);
return;

View File

@ -203,8 +203,15 @@ namespace MediaBrowser.XbmcMetadata.Savers
// On Windows, saving the file will fail if the file is hidden or readonly
FileSystem.SetAttributes(path, false, false);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
var fileStreamOptions = new FileStreamOptions()
{
Mode = FileMode.Create,
Access = FileAccess.Write,
Share = FileShare.None,
PreallocationSize = stream.Length
};
using (var filestream = new FileStream(path, fileStreamOptions))
{
stream.CopyTo(filestream);
}