|
|
|
@ -18,6 +18,10 @@ namespace NzbDrone.Mono
|
|
|
|
|
private readonly IProcMountProvider _procMountProvider;
|
|
|
|
|
private readonly ISymbolicLinkResolver _symLinkResolver;
|
|
|
|
|
|
|
|
|
|
// Mono supports sending -1 for a uint to indicate that the owner or group should not be set
|
|
|
|
|
// `unchecked((uint)-1)` and `uint.MaxValue` are the same thing.
|
|
|
|
|
private const uint UNCHANGED_ID = uint.MaxValue;
|
|
|
|
|
|
|
|
|
|
public DiskProvider(IProcMountProvider procMountProvider, ISymbolicLinkResolver symLinkResolver)
|
|
|
|
|
{
|
|
|
|
|
_procMountProvider = procMountProvider;
|
|
|
|
@ -75,50 +79,77 @@ namespace NzbDrone.Mono
|
|
|
|
|
|
|
|
|
|
public override void SetPermissions(string path, string mask, string user, string group)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("Setting permissions: {0} on {1}", mask, path);
|
|
|
|
|
SetPermissions(path, mask);
|
|
|
|
|
SetOwner(path, user, group);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var filePermissions = NativeConvert.FromOctalPermissionString(mask);
|
|
|
|
|
public override System.Collections.Generic.List<IMount> GetMounts()
|
|
|
|
|
{
|
|
|
|
|
return base.GetMounts()
|
|
|
|
|
.Concat(_procMountProvider.GetMounts())
|
|
|
|
|
.DistinctBy(v => v.RootDirectory)
|
|
|
|
|
.ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Syscall.chmod(path, filePermissions) < 0)
|
|
|
|
|
public override long? GetTotalSize(string path)
|
|
|
|
|
{
|
|
|
|
|
var error = Stdlib.GetLastError();
|
|
|
|
|
Ensure.That(path, () => path).IsValidPath();
|
|
|
|
|
|
|
|
|
|
throw new LinuxPermissionsException("Error setting file permissions: " + error);
|
|
|
|
|
}
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var mount = GetMount(path);
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(user) || string.IsNullOrWhiteSpace(group))
|
|
|
|
|
if (mount == null) return null;
|
|
|
|
|
|
|
|
|
|
return mount.TotalSize;
|
|
|
|
|
}
|
|
|
|
|
catch (InvalidOperationException e)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("User or Group for chown not configured, skipping chown.");
|
|
|
|
|
return;
|
|
|
|
|
Logger.Error(e, "Couldn't get total space for " + path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint userId;
|
|
|
|
|
uint groupId;
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!uint.TryParse(user, out userId))
|
|
|
|
|
public override bool TryCreateHardLink(string source, string destination)
|
|
|
|
|
{
|
|
|
|
|
var u = Syscall.getpwnam(user);
|
|
|
|
|
|
|
|
|
|
if (u == null)
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
throw new LinuxPermissionsException("Unknown user: {0}", user);
|
|
|
|
|
UnixFileSystemInfo.GetFileSystemEntry(source).CreateLink(destination);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug(ex, string.Format("Hardlink '{0}' to '{1}' failed.", source, destination));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
userId = u.pw_uid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!uint.TryParse(group, out groupId))
|
|
|
|
|
private void SetPermissions(string path, string mask)
|
|
|
|
|
{
|
|
|
|
|
var g = Syscall.getgrnam(group);
|
|
|
|
|
Logger.Debug("Setting permissions: {0} on {1}", mask, path);
|
|
|
|
|
|
|
|
|
|
if (g == null)
|
|
|
|
|
var filePermissions = NativeConvert.FromOctalPermissionString(mask);
|
|
|
|
|
|
|
|
|
|
if (Syscall.chmod(path, filePermissions) < 0)
|
|
|
|
|
{
|
|
|
|
|
throw new LinuxPermissionsException("Unknown group: {0}", group);
|
|
|
|
|
var error = Stdlib.GetLastError();
|
|
|
|
|
|
|
|
|
|
throw new LinuxPermissionsException("Error setting file permissions: " + error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
groupId = g.gr_gid;
|
|
|
|
|
private void SetOwner(string path, string user, string group)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(user) && string.IsNullOrWhiteSpace(group))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("User and Group for chown not configured, skipping chown.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var userId = GetUserId(user);
|
|
|
|
|
var groupId = GetGroupId(group);
|
|
|
|
|
|
|
|
|
|
if (Syscall.chown(path, userId, groupId) < 0)
|
|
|
|
|
{
|
|
|
|
|
var error = Stdlib.GetLastError();
|
|
|
|
@ -127,46 +158,54 @@ namespace NzbDrone.Mono
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override System.Collections.Generic.List<IMount> GetMounts()
|
|
|
|
|
private uint GetUserId(string user)
|
|
|
|
|
{
|
|
|
|
|
return base.GetMounts()
|
|
|
|
|
.Concat(_procMountProvider.GetMounts())
|
|
|
|
|
.DistinctBy(v => v.RootDirectory)
|
|
|
|
|
.ToList();
|
|
|
|
|
if (user.IsNullOrWhiteSpace())
|
|
|
|
|
{
|
|
|
|
|
return UNCHANGED_ID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override long? GetTotalSize(string path)
|
|
|
|
|
{
|
|
|
|
|
Ensure.That(path, () => path).IsValidPath();
|
|
|
|
|
uint userId;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
if (uint.TryParse(user, out userId))
|
|
|
|
|
{
|
|
|
|
|
var mount = GetMount(path);
|
|
|
|
|
return userId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mount == null) return null;
|
|
|
|
|
var u = Syscall.getpwnam(user);
|
|
|
|
|
|
|
|
|
|
return mount.TotalSize;
|
|
|
|
|
}
|
|
|
|
|
catch (InvalidOperationException e)
|
|
|
|
|
if (u == null)
|
|
|
|
|
{
|
|
|
|
|
Logger.Error(e, "Couldn't get total space for " + path);
|
|
|
|
|
throw new LinuxPermissionsException("Unknown user: {0}", user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
return u.pw_uid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool TryCreateHardLink(string source, string destination)
|
|
|
|
|
private uint GetGroupId(string group)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
if (group.IsNullOrWhiteSpace())
|
|
|
|
|
{
|
|
|
|
|
UnixFileSystemInfo.GetFileSystemEntry(source).CreateLink(destination);
|
|
|
|
|
return true;
|
|
|
|
|
return UNCHANGED_ID;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
|
|
|
|
uint groupId;
|
|
|
|
|
|
|
|
|
|
if (uint.TryParse(group, out groupId))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug(ex, string.Format("Hardlink '{0}' to '{1}' failed.", source, destination));
|
|
|
|
|
return false;
|
|
|
|
|
return groupId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var g = Syscall.getgrnam(group);
|
|
|
|
|
|
|
|
|
|
if (g == null)
|
|
|
|
|
{
|
|
|
|
|
throw new LinuxPermissionsException("Unknown group: {0}", group);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g.gr_gid;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|