Implement mono logic to not set owner/group with chown

New: Allow Owner or Group to be left blank to not set it when changing owner (mono only)
Closes #1220
pull/2/head
Mark McDowall 9 years ago
parent ab7b427241
commit 5942ddf9f1

@ -18,6 +18,10 @@ namespace NzbDrone.Mono
private readonly IProcMountProvider _procMountProvider; private readonly IProcMountProvider _procMountProvider;
private readonly ISymbolicLinkResolver _symLinkResolver; 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) public DiskProvider(IProcMountProvider procMountProvider, ISymbolicLinkResolver symLinkResolver)
{ {
_procMountProvider = procMountProvider; _procMountProvider = procMountProvider;
@ -75,50 +79,77 @@ namespace NzbDrone.Mono
public override void SetPermissions(string path, string mask, string user, string group) 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."); Logger.Error(e, "Couldn't get total space for " + path);
return;
} }
uint userId; return null;
uint groupId; }
if (!uint.TryParse(user, out userId)) public override bool TryCreateHardLink(string source, string destination)
{ {
var u = Syscall.getpwnam(user); try
if (u == null)
{ {
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) if (Syscall.chown(path, userId, groupId) < 0)
{ {
var error = Stdlib.GetLastError(); 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() if (user.IsNullOrWhiteSpace())
.Concat(_procMountProvider.GetMounts()) {
.DistinctBy(v => v.RootDirectory) return UNCHANGED_ID;
.ToList();
} }
public override long? GetTotalSize(string path) uint userId;
{
Ensure.That(path, () => path).IsValidPath();
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; if (u == null)
}
catch (InvalidOperationException e)
{ {
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 UNCHANGED_ID;
return true;
} }
catch (Exception ex)
uint groupId;
if (uint.TryParse(group, out groupId))
{ {
Logger.Debug(ex, string.Format("Hardlink '{0}' to '{1}' failed.", source, destination)); return groupId;
return false; }
var g = Syscall.getgrnam(group);
if (g == null)
{
throw new LinuxPermissionsException("Unknown group: {0}", group);
} }
return g.gr_gid;
} }
} }
} }

Loading…
Cancel
Save