Skip to content

Commit

Permalink
Add UnixfilePermissions enum.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmds committed Mar 31, 2024
1 parent 2a9766e commit 58f7cd0
Show file tree
Hide file tree
Showing 12 changed files with 235 additions and 156 deletions.
39 changes: 23 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ class SshDataStream : Stream
class SftpClient : IDisposable
{
ValueTask<SftpFile> OpenOrCreateFileAsync(string path, FileAccess access, CancellationToken cancellationToken = default);
ValueTask<SftpFile> OpenOrCreateFileAsync(string path, FileAccess access, UnixFileMode createPermissions, CancellationToken cancellationToken = default);
ValueTask<SftpFile> OpenOrCreateFileAsync(string path, FileAccess access, UnixFilePermissions createPermissions, CancellationToken cancellationToken = default);
ValueTask<SftpFile> OpenOrCreateFileAsync(string path, FileAccess access, OpenMode mode, CancellationToken cancellationToken = default);
ValueTask<SftpFile> OpenOrCreateFileAsync(string path, FileAccess access, OpenMode mode, UnixFileMode createPermissions, CancellationToken cancellationToken = default);
ValueTask<SftpFile> OpenOrCreateFileAsync(string path, FileAccess access, OpenMode mode, UnixFilePermissions createPermissions, CancellationToken cancellationToken = default);
ValueTask<SftpFile> CreateNewFileAsync(string path, FileAccess access, CancellationToken cancellationToken = default);
ValueTask<SftpFile> CreateNewFileAsync(string path, FileAccess access, UnixFileMode permissions, CancellationToken cancellationToken = default);
ValueTask<SftpFile> CreateNewFileAsync(string path, FileAccess access, OpenMode mode, UnixFileMode permissions, CancellationToken cancellationToken = default);
ValueTask<SftpFile> CreateNewFileAsync(string path, FileAccess access, UnixFilePermissions permissions, CancellationToken cancellationToken = default);
ValueTask<SftpFile> CreateNewFileAsync(string path, FileAccess access, OpenMode mode, UnixFilePermissions permissions, CancellationToken cancellationToken = default);
ValueTask<SftpFile> CreateNewFileAsync(string path, FileAccess access, OpenMode mode, CancellationToken cancellationToken = default);

// Returns null if the file does not exist.
Expand All @@ -130,14 +130,14 @@ class SftpClient : IDisposable

// Does not throw if the path is an existing directory, or a link to one.
ValueTask CreateDirectoryAsync(string path, CancellationToken cancellationToken = default);
ValueTask CreateDirectoryAsync(string path, UnixFileMode createPermissions, CancellationToken cancellationToken = default);
ValueTask CreateDirectoryAsync(string path, UnixFilePermissions createPermissions, CancellationToken cancellationToken = default);
ValueTask CreateDirectoryAsync(string path, bool createParents, CancellationToken cancellationToken = default);
ValueTask CreateDirectoryAsync(string path, bool createParents, UnixFileMode createPermissions, CancellationToken cancellationToken = default);
ValueTask CreateDirectoryAsync(string path, bool createParents, UnixFilePermissions createPermissions, CancellationToken cancellationToken = default);
// Throws if the path exists.
ValueTask CreateNewDirectoryAsync(string path, CancellationToken cancellationToken = default);
ValueTask CreateNewDirectoryAsync(string path, UnixFileMode permissions, CancellationToken cancellationToken = default);
ValueTask CreateNewDirectoryAsync(string path, UnixFilePermissions permissions, CancellationToken cancellationToken = default);
ValueTask CreateNewDirectoryAsync(string path, bool createParents, CancellationToken cancellationToken = default);
ValueTask CreateNewDirectoryAsync(string path, bool createParents, UnixFileMode permissions, CancellationToken cancellationToken = default);
ValueTask CreateNewDirectoryAsync(string path, bool createParents, UnixFilePermissions permissions, CancellationToken cancellationToken = default);

// Does not throw if the path did not exist.
ValueTask DeleteDirectoryAsync(string path, CancellationToken cancellationToken = default);
Expand All @@ -150,9 +150,9 @@ class SftpClient : IDisposable
IAsyncEnumerable<T> GetDirectoryEntriesAsync<T>(string path, SftpFileEntryTransform<T> transform, EnumerationOptions? options = null);

ValueTask UploadFileAsync(string localFilePath, string remoteFilePath, CancellationToken cancellationToken = default);
ValueTask UploadFileAsync(string localFilePath, string remoteFilePath, UnixFileMode permissions, CancellationToken cancellationToken = default);
ValueTask UploadFileAsync(string localFilePath, string remoteFilePath, UnixFilePermissions permissions, CancellationToken cancellationToken = default);
ValueTask UploadFileAsync(string localFilePath, string remoteFilePath, bool overwrite, CancellationToken cancellationToken = default);
ValueTask UploadFileAsync(string localFilePath, string remoteFilePath, bool overwrite, UnixFileMode createPermissions, CancellationToken cancellationToken = default);
ValueTask UploadFileAsync(string localFilePath, string remoteFilePath, bool overwrite, UnixFilePermissions createPermissions, CancellationToken cancellationToken = default);
ValueTask UploadDirectoryEntriesAsync(string localDirPath, string remoteDirPath, CancellationToken cancellationToken = default);
ValueTask UploadDirectoryEntriesAsync(string localDirPath, string remoteDirPath, UploadEntriesOptions? options, CancellationToken cancellationToken = default);

Expand Down Expand Up @@ -227,13 +227,14 @@ class FileEntryAttributes
long? Length { get; set; }
int? Uid { get; set; }
int? Gid { get; set; }
PosixFileMode? FileMode { get; set; }
public UnixFileType? FileType { get; set; }
public UnixFilePermissions? Permissions { get; set; }
DateTimeOffset? LastAccessTime { get; set; }
DateTimeOffset? LastWriteTime { get; set; }
Dictionary<string, string>? ExtendedAttributes { get; set; }

UnixFileType? FileType { get; }
UnixFileMode? Permissions { get; }
UnixFilePermissions? Permissions { get; }
}
class EnumerationOptions
{
Expand Down Expand Up @@ -261,9 +262,8 @@ ref struct SftpFileEntry
long Length { get; }
int Uid { get; }
int Gid { get; }
PosixFileMode FileMode { get; }
UnixFileType FileType { get; }
UnixFileMode Permissions { get; }
UnixFilePermissions Permissions { get; }
DateTimeOffset LastAccessTime { get; }
DateTimeOffset LastWriteTime { get; }
ReadOnlySpan<char> Path { get; }
Expand All @@ -273,7 +273,7 @@ ref struct SftpFileEntry
string ToPath()
}
[Flags]
enum PosixFileMode
enum UnixFilePermissions // values match System.IO.UnixFileMode.
{
None,
OtherExecute,
Expand All @@ -288,7 +288,14 @@ enum PosixFileMode
StickyBit,
SetGroup,
SetUser,

}
static class UnixFilePemissionExtensions
{
static UnixFilePermissions ToUnixFilePermissions(this System.IO.UnixFileMode mode);
static System.IO.UnixFileMode ToUnixFileMode(this UnixFilePermissions permissions);
}
enum UnixFileType
{
RegularFile,
Directory,
SymbolicLink,
Expand Down
8 changes: 2 additions & 6 deletions src/Tmds.Ssh/FileEntryAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,10 @@ public sealed class FileEntryAttributes
public long? Length { get; set; }
public int? Uid { get; set; }
public int? Gid { get; set; }
public PosixFileMode? FileMode { get; set; }
public UnixFileType? FileType { get; set; }
public UnixFilePermissions? Permissions { get; set; }
public DateTimeOffset? LastAccessTime { get; set; } // ATime
public DateTimeOffset? LastWriteTime { get; set; } // MTime
public Dictionary<string, string>? ExtendedAttributes { get; set; }

public UnixFileType? FileType => (UnixFileType?)(FileMode & (PosixFileMode)0xf000);
#if NET7_0_OR_GREATER
public UnixFileMode? Permissions => (UnixFileMode?)(FileMode & (PosixFileMode)0x0fff);
#endif
}
}
33 changes: 0 additions & 33 deletions src/Tmds.Ssh/PosixFileMode.cs

This file was deleted.

27 changes: 24 additions & 3 deletions src/Tmds.Ssh/SftpClient.Reader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;

namespace Tmds.Ssh
{
Expand Down Expand Up @@ -85,7 +86,8 @@ public FileEntryAttributes ReadFileAttributes(FileEntryAttributes attributes)
long? length = default;
int? uid = default;
int? gid = default;
PosixFileMode? fileMode = default;
UnixFileType? fileType = default;
UnixFilePermissions? permissions = default;
DateTimeOffset? lastAccessTime = default;
DateTimeOffset? lastWriteTime = default;
Dictionary<string, string>? extendedAttributes = default;
Expand All @@ -102,7 +104,7 @@ public FileEntryAttributes ReadFileAttributes(FileEntryAttributes attributes)
}
if ((flags & 4) != 0)
{
fileMode = (PosixFileMode)ReadInt();
(permissions, fileType) = ReadFileMode();
}
if ((flags & 8) != 0)
{
Expand All @@ -125,7 +127,8 @@ public FileEntryAttributes ReadFileAttributes(FileEntryAttributes attributes)
attributes.Length = length;
attributes.Uid = uid;
attributes.Gid = gid;
attributes.FileMode = fileMode;
attributes.Permissions = permissions;
attributes.FileType = fileType;
attributes.LastAccessTime = lastAccessTime;
attributes.LastWriteTime = lastWriteTime;
attributes.ExtendedAttributes = extendedAttributes;
Expand All @@ -137,6 +140,24 @@ public PacketType ReadPacketType()
{
return (PacketType)ReadByte();
}

public (UnixFilePermissions, UnixFileType) ReadFileMode()
{
int mode = ReadInt();
UnixFilePermissions permissions = (UnixFilePermissions)(mode & 0xfff);
UnixFileType fileType = ((UnixFileTypeByte)(mode >> 12)) switch
{
UnixFileTypeByte.RegularFile => UnixFileType.RegularFile,
UnixFileTypeByte.Directory => UnixFileType.Directory,
UnixFileTypeByte.SymbolicLink => UnixFileType.SymbolicLink,
UnixFileTypeByte.CharacterDevice => UnixFileType.CharacterDevice,
UnixFileTypeByte.BlockDevice => UnixFileType.BlockDevice,
UnixFileTypeByte.Socket => UnixFileType.Socket,
UnixFileTypeByte.Fifo => UnixFileType.Fifo,
_ => throw new InvalidDataException($"Invalid mode: {mode}.")
};
return (permissions, fileType);
}
}
}
}
26 changes: 21 additions & 5 deletions src/Tmds.Ssh/SftpClient.Writer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,22 @@ public void WriteAttributes(FileEntryAttributes? attributes)
}
else
{
WriteAttributes(attributes.Length, attributes.Uid, attributes.Gid, attributes.FileMode, attributes.LastAccessTime, attributes.LastWriteTime, attributes.ExtendedAttributes);
WriteAttributes(attributes.Length, attributes.Uid, attributes.Gid, attributes.Permissions, attributes.FileType, attributes.LastAccessTime, attributes.LastWriteTime, attributes.ExtendedAttributes);
}
}

public void WriteAttributes(
long? length = default,
int? uid = default,
int? gid = default,
PosixFileMode? fileMode = default,
UnixFilePermissions? permissions = default,
UnixFileType? fileType = default,
DateTimeOffset? lastAccessTime = default,
DateTimeOffset? lastWriteTime = default,
Dictionary<string, string>? extendedAttributes = default
)
{
bool setMode = permissions.HasValue;
uint flags = 0;
if (length.HasValue)
{
Expand All @@ -112,7 +114,7 @@ public void WriteAttributes(
}
flags |= 2;
}
if (fileMode.HasValue)
if (setMode)
{
flags |= 4;
}
Expand Down Expand Up @@ -145,9 +147,9 @@ public void WriteAttributes(
{
WriteInt(gid.Value);
}
if (fileMode.HasValue)
if (setMode)
{
WriteInt((int)fileMode.Value);
WriteFileMode(permissions, fileType);
}
if (lastAccessTime.HasValue)
{
Expand All @@ -168,6 +170,20 @@ public void WriteAttributes(
}
}

private void WriteFileMode(UnixFilePermissions? permissions, UnixFileType? fileType)
{
int mode = 0;
if (permissions.HasValue)
{
mode |= permissions.Value.GetMode();
}
if (fileType.HasValue)
{
mode |= fileType.Value.GetMode();
}
WriteInt(mode);
}

public unsafe void WriteString(ReadOnlySpan<char> value)
{
byte[]? poolBuffer = null;
Expand Down
Loading

0 comments on commit 58f7cd0

Please sign in to comment.