aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.IsoMounter/IsoManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.IsoMounter/IsoManager.cs')
-rw-r--r--MediaBrowser.IsoMounter/IsoManager.cs200
1 files changed, 200 insertions, 0 deletions
diff --git a/MediaBrowser.IsoMounter/IsoManager.cs b/MediaBrowser.IsoMounter/IsoManager.cs
new file mode 100644
index 000000000..22f09addf
--- /dev/null
+++ b/MediaBrowser.IsoMounter/IsoManager.cs
@@ -0,0 +1,200 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Kernel;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.IsoMounter
+{
+ /// <summary>
+ /// Class IsoManager
+ /// </summary>
+ public class IsoManager : BaseManager<IKernel>, IIsoManager
+ {
+ /// <summary>
+ /// The mount semaphore - limit to four at a time.
+ /// </summary>
+ private readonly SemaphoreSlim _mountSemaphore = new SemaphoreSlim(4,4);
+
+ /// <summary>
+ /// The PFM API
+ /// </summary>
+ private PfmApi _pfmApi;
+ /// <summary>
+ /// The _PFM API initialized
+ /// </summary>
+ private bool _pfmApiInitialized;
+ /// <summary>
+ /// The _PFM API sync lock
+ /// </summary>
+ private object _pfmApiSyncLock = new object();
+ /// <summary>
+ /// Gets the display prefs.
+ /// </summary>
+ /// <value>The display prefs.</value>
+ private PfmApi PfmApi
+ {
+ get
+ {
+ LazyInitializer.EnsureInitialized(ref _pfmApi, ref _pfmApiInitialized, ref _pfmApiSyncLock, () =>
+ {
+ var err = PfmStatic.InstallCheck();
+
+ if (err != PfmInst.installed)
+ {
+ throw new Exception("Pismo File Mount Audit Package is not installed");
+ }
+
+ PfmApi pfmApi;
+
+ err = PfmStatic.ApiFactory(out pfmApi);
+
+ if (err != 0)
+ {
+ throw new IOException("Unable to open PFM Api. Pismo File Mount Audit Package is probably not installed.");
+ }
+
+ return pfmApi;
+ });
+ return _pfmApi;
+ }
+ }
+
+ /// <summary>
+ /// The _has initialized
+ /// </summary>
+ private bool _hasInitialized;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="IsoManager" /> class.
+ /// </summary>
+ /// <param name="kernel">The kernel.</param>
+ public IsoManager(IKernel kernel)
+ : base(kernel)
+ {
+ }
+
+ /// <summary>
+ /// The _my PFM file mount UI
+ /// </summary>
+ private readonly MyPfmFileMountUi _myPfmFileMountUi = new MyPfmFileMountUi();
+
+ /// <summary>
+ /// Mounts the specified iso path.
+ /// </summary>
+ /// <param name="isoPath">The iso path.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <param name="visibleToAllProcesses">if set to <c>true</c> [visible to all processes].</param>
+ /// <returns>IsoMount.</returns>
+ /// <exception cref="System.ArgumentNullException">isoPath</exception>
+ /// <exception cref="System.IO.IOException">Unable to create mount.</exception>
+ public async Task<IIsoMount> Mount(string isoPath, CancellationToken cancellationToken, bool visibleToAllProcesses = true)
+ {
+ if (string.IsNullOrEmpty(isoPath))
+ {
+ throw new ArgumentNullException("isoPath");
+ }
+
+ PfmFileMount mount;
+ var err = PfmApi.FileMountCreate(out mount);
+
+ if (err != 0)
+ {
+ throw new IOException("Unable to create mount for " + isoPath);
+ }
+
+ _hasInitialized = true;
+
+ var fmp = new PfmFileMountCreateParams { };
+
+ fmp.ui = _myPfmFileMountUi;
+
+ fmp.fileMountFlags |= PfmFileMountFlag.inProcess;
+
+ if (visibleToAllProcesses)
+ {
+ fmp.visibleProcessId = PfmVisibleProcessId.all;
+ }
+
+ fmp.mountFileName = isoPath;
+
+ // unc only
+ fmp.mountFlags |= PfmMountFlag.uncOnly;
+ fmp.mountFlags |= PfmMountFlag.noShellNotify;
+ fmp.mountFlags |= PfmMountFlag.readOnly;
+
+ Logger.Info("Mounting {0}", isoPath);
+
+ await _mountSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ err = mount.Start(fmp);
+
+ if (err != 0)
+ {
+ _mountSemaphore.Release();
+ mount.Dispose();
+ throw new IOException("Unable to start mount for " + isoPath);
+ }
+
+ err = mount.WaitReady();
+
+ if (err != 0)
+ {
+ _mountSemaphore.Release();
+ mount.Dispose();
+ throw new IOException("Unable to start mount for " + isoPath);
+ }
+
+ return new IsoMount(mount, isoPath, this);
+ }
+
+ /// <summary>
+ /// Releases unmanaged and - optionally - managed resources.
+ /// </summary>
+ /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+ protected override void Dispose(bool dispose)
+ {
+ if (dispose)
+ {
+ if (_hasInitialized)
+ {
+ Logger.Info("Disposing PfmPapi");
+ _pfmApi.Dispose();
+
+ Logger.Info("PfmStatic.ApiUnload");
+ PfmStatic.ApiUnload();
+ }
+ }
+
+ base.Dispose(dispose);
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this instance can mount.
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <returns><c>true</c> if this instance can mount the specified path; otherwise, <c>false</c>.</returns>
+ /// <value><c>true</c> if this instance can mount; otherwise, <c>false</c>.</value>
+ public bool CanMount(string path)
+ {
+ try
+ {
+ return string.Equals(Path.GetExtension(path), ".iso", StringComparison.OrdinalIgnoreCase) && PfmApi != null;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Called when [unmount].
+ /// </summary>
+ /// <param name="mount">The mount.</param>
+ internal void OnUnmount(IsoMount mount)
+ {
+ _mountSemaphore.Release();
+ }
+ }
+}