Storage STG97 Features (#6396)

* Storage STG97/NFS REST (#6245)

* Update rest layer and some structs

* Add file support.

* Add new apis

* Update test

* resolve clang error and cspell

* Update comments

* update comments

* Storage STG97/NFS REST Part2(Impl+test) (#6285)

* add test cases and some code change.

* update logic

* fix pipeline failure

* fix cspell

* update test record

* Fix pipeline failure

* Fix test case failure

* Storage/STG97 Remove Create/Get SymbolicLink API (#6304)

* Remove Create/Get SymbolicLink API

* update test record

* Fix archboard comments (#6324)
This commit is contained in:
microzchang 2025-02-07 14:47:09 +08:00 committed by GitHub
parent 366e05ea1a
commit b7bd086776
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 3196 additions and 573 deletions

View File

@ -225,6 +225,7 @@ void TestProxyManager::SetProxySanitizer()
"x-ms-file-change-time",
"x-ms-file-creation-time",
"x-ms-file-last-write-time",
"x-ms-link-text",
"x-ms-rename-source",
"x-ms-immutability-policy-until-date",
};

View File

@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "cpp",
"TagPrefix": "cpp/storage",
"Tag": "cpp/storage_f9f7bb54df"
"Tag": "cpp/storage_57a579efb6"
}

View File

@ -9,7 +9,7 @@
namespace Azure { namespace Storage { namespace Sas {
namespace {
constexpr static const char* SasVersion = "2025-01-05";
constexpr static const char* SasVersion = "2025-05-05";
}
void AccountSasBuilder::SetPermissions(AccountSasPermissions permissions)

View File

@ -379,6 +379,19 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
const UploadFileRangeFromUriOptions& options = UploadFileRangeFromUriOptions(),
const Azure::Core::Context& context = Azure::Core::Context()) const;
/**
* @brief NFS only. Creates a hard link to the file specified by path.
* @param targetFile Path of the file to create the hard link to, not including the share.
* @param options Optional parameters to create this file's symbolic link.
* @param context Context for cancelling long running operations.
* @return Azure::Response<Models::CreateFileHardLinkResult> containing the returned
* information.
*/
Azure::Response<Models::CreateFileHardLinkResult> CreateHardLink(
const std::string& targetFile,
const CreateHardLinkOptions& options = CreateHardLinkOptions(),
const Azure::Core::Context& context = Azure::Core::Context()) const;
private:
Azure::Core::Url m_shareFileUrl;
std::shared_ptr<Azure::Core::Http::_internal::HttpPipeline> m_pipeline;

View File

@ -18,6 +18,208 @@
namespace Azure { namespace Storage { namespace Files { namespace Shares {
namespace Models {
enum class RolePermissions
{
/*
* @brief No permissions.
*/
None = 0,
/*
* @brief The execute permission.
*/
Execute = 1,
/*
* @brief The write permission.
*/
Write = 2,
/*
* @brief The read permission.
*/
Read = 4,
};
inline RolePermissions operator|(const RolePermissions& lhs, const RolePermissions& rhs)
{
using type = std::underlying_type_t<RolePermissions>;
return static_cast<RolePermissions>(static_cast<type>(lhs) | static_cast<type>(rhs));
}
inline RolePermissions operator&(const RolePermissions& lhs, const RolePermissions& rhs)
{
using type = std::underlying_type_t<RolePermissions>;
return static_cast<RolePermissions>(static_cast<type>(lhs) & static_cast<type>(rhs));
}
/**
* @brief The mode permissions of the file or directory.
*/
struct NfsFileMode final
{
/**
* @brief Permissions the owner has over the file or directory.
*/
RolePermissions Owner;
/**
* @brief Permissions the group has over the file or directory.
*/
RolePermissions Group;
/**
* @brief Permissions other have over the file or directory.
*/
RolePermissions Other;
/**
* @brief Set effective user ID (setuid) on the file or directory.
*/
bool EffectiveUserIdentity = false;
/**
* @brief Set effective group ID (setgid) on the file or directory.
*/
bool EffectiveGroupIdentity = false;
/**
* @brief The sticky bit may be set on directories. The files in that directory may only be
* renamed or deleted by the file's owner, the directory's owner, or the root user.
*/
bool StickyBit = false;
/**
* @brief Returns the octal representation of NfsFileMode as a string.
*/
std::string ToOctalFileMode() const;
/**
* @brief Returns NfsFileMode as a string in symbolic notation.
*/
std::string ToSymbolicFileMode() const;
/**
* @brief Returns a NfsFileMode from the octal string representation.
*
* @param modeString A 4-digit octal string representation of a File Mode.
*/
static NfsFileMode ParseOctalFileMode(const std::string& modeString);
/**
* @brief Returns a NfsFileMode from the symbolic string representation.
*
* @param modeString A 9-character symbolic string representation of a File Mode.
*/
static NfsFileMode ParseSymbolicFileMode(const std::string& modeString);
};
/**
* @brief NFS properties. Note that these properties only apply to files or directories in
* premium NFS file accounts.
*/
struct FilePosixProperties final
{
/**
* NFS only. The mode of the file or directory.
*/
Nullable<NfsFileMode> FileMode;
/**
* NFS only. The owner of the file or directory.
*/
Nullable<std::string> Owner;
/**
* NFS only. The owning group of the file or directory.
*/
Nullable<std::string> Group;
/**
* NFS only. Type of the file or directory.
*/
Nullable<Models::NfsFileType> NfsFileType;
/**
* NFS only. The link count of the file or directory.
*/
Nullable<std::int64_t> LinkCount;
};
} // namespace Models
/**
* Smb Properties to copy from the source file.
*/
enum class CopyableFileSmbPropertyFlags
{
/**
* None.
*/
None = 0,
/**
* File Attributes.
*/
FileAttributes = 1,
/**
* Created On.
*/
CreatedOn = 2,
/**
* Last Written On.
*/
LastWrittenOn = 4,
/**
* Changed On.
*/
ChangedOn = 8,
/**
* Permission
*/
Permission = 16,
/**
* All.
*/
All = ~None
};
inline CopyableFileSmbPropertyFlags operator|(
CopyableFileSmbPropertyFlags lhs,
CopyableFileSmbPropertyFlags rhs)
{
using type = std::underlying_type_t<CopyableFileSmbPropertyFlags>;
return static_cast<CopyableFileSmbPropertyFlags>(
static_cast<type>(lhs) | static_cast<type>(rhs));
}
inline CopyableFileSmbPropertyFlags& operator|=(
CopyableFileSmbPropertyFlags& lhs,
CopyableFileSmbPropertyFlags rhs)
{
lhs = lhs | rhs;
return lhs;
}
inline CopyableFileSmbPropertyFlags operator&(
CopyableFileSmbPropertyFlags lhs,
CopyableFileSmbPropertyFlags rhs)
{
using type = std::underlying_type_t<CopyableFileSmbPropertyFlags>;
return static_cast<CopyableFileSmbPropertyFlags>(
static_cast<type>(lhs) & static_cast<type>(rhs));
}
inline CopyableFileSmbPropertyFlags& operator&=(
CopyableFileSmbPropertyFlags& lhs,
CopyableFileSmbPropertyFlags rhs)
{
lhs = lhs & rhs;
return lhs;
}
/**
* @brief Audiences available for share service
*
@ -389,6 +591,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
* SMB properties to set for the directory.
*/
Models::FileSmbProperties SmbProperties;
/**
* The NFS related properties for the file.
*/
Models::FilePosixProperties PosixProperties;
};
/**
@ -550,6 +757,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
* returned in SDDL format.
*/
Nullable<Models ::FilePermissionFormat> FilePermissionFormat;
/**
* The NFS related properties for the file.
*/
Models::FilePosixProperties PosixProperties;
};
/**
@ -695,6 +907,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
* The operation will only succeed if the access condition is met.
*/
LeaseAccessConditions AccessConditions;
/**
* The NFS related properties for the file.
*/
Models::FilePosixProperties PosixProperties;
};
/**
@ -766,6 +983,17 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
*/
Azure::Nullable<Models::PermissionCopyMode> PermissionCopyMode;
/**
* Smb Properties to copy from the source file.
* If this flag is nullable, it will use the value of source file(except ChangedOn, it will be
* default value) if the property is not set.
* If this flag is disabled, it will use the default
* value of destination file if the property is not set.
* If this flag is enabled, it will use the value of source file no
* matter the property is set or not.
*/
Azure::Nullable<CopyableFileSmbPropertyFlags> SmbPropertiesToCopy;
/**
* Specifies the option to overwrite the target file if it already exists and has
* read-only attribute set.
@ -782,6 +1010,23 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
* The operation will only succeed if the access condition is met.
*/
LeaseAccessConditions AccessConditions;
/**
* The NFS related properties for the file.
*/
Models::FilePosixProperties PosixProperties;
/**
* Optional, only applicable to NFS Files. If not populated, the destination file will have the
* default File Mode.
*/
Azure::Nullable<Models::ModeCopyMode> ModeCopyMode;
/**
* Optional, only applicable to NFS Files. If not populated, the destination file will have the
* default Owner and Group.
*/
Azure::Nullable<Models::OwnerCopyMode> OwnerCopyMode;
};
/**
@ -835,6 +1080,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
* The operation will only succeed if the access condition is met.
*/
LeaseAccessConditions AccessConditions;
/**
* The NFS related properties for the file.
*/
Models::FilePosixProperties PosixProperties;
};
/**
@ -1066,6 +1316,11 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
*/
Nullable<Models::FilePermissionFormat> FilePermissionFormat;
/**
* The NFS related properties for the file.
*/
Models::FilePosixProperties PosixProperties;
/**
* @brief Options for parallel transfer.
*/
@ -1131,4 +1386,16 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
struct RenewLeaseOptions final
{
};
/**
* @brief Optional parameters for
* #Azure::Storage::Files::Shares::ShareFileClient::CreateHardLink.
*/
struct CreateHardLinkOptions final
{
/**
* Specify the access condition for the path.
*/
LeaseAccessConditions AccessConditions;
};
}}}} // namespace Azure::Storage::Files::Shares

View File

@ -48,6 +48,127 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
bool IsServerEncrypted = bool();
};
/**
* @brief Detailed information of the downloaded file.
*/
struct DownloadFileDetails final
{
/**
* The ETag contains a value that you can use to perform operations conditionally. If the
* request version is 2011-08-18 or newer, the ETag value will be in quotes.
*/
Azure::ETag ETag;
/**
* Returns the date and time the file was last modified. Any operation that modifies the
* file, including an update of the file's metadata or properties, changes the last-modified
* time of the file.
*/
DateTime LastModified;
/**
* A set of name-value pairs associated with the share or file.
*/
Core::CaseInsensitiveMap Metadata;
/**
* String identifier for this copy operation. Use with Get File Properties to check the
* status of this copy operation, or pass to Abort Copy File to abort a pending copy.
*/
Nullable<std::string> CopyId;
/**
* URL up to 2 KB in length that specifies the source file or file used in the last
* attempted Copy File operation where this file was the destination file. This header does
* not appear if this file has never been the destination in a Copy File operation, or if
* this file has been modified after a concluded Copy File operation using Set File
* Properties, Put File, or Put Block List.
*/
Nullable<std::string> CopySource;
/**
* Status of a copy operation.
*/
Nullable<Models::CopyStatus> CopyStatus;
/**
* Only appears when x-ms-copy-status is failed or pending. Describes the cause of the last
* fatal or non-fatal copy operation failure. This header does not appear if this file has
* never been the destination in a Copy File operation, or if this file has been modified
* after a concluded Copy File operation using Set File Properties, Put File, or Put Block
* List.
*/
Nullable<std::string> CopyStatusDescription;
/**
* Contains the number of bytes copied and the total bytes in the source in the last
* attempted Copy File operation where this file was the destination file. Can show between
* 0 and Content-Length bytes copied. This header does not appear if this file has never
* been the destination in a Copy File operation, or if this file has been modified after a
* concluded Copy File operation using Set File Properties, Put File, or Put Block List.
*/
Nullable<std::string> CopyProgress;
/**
* Conclusion time of the last attempted Copy File operation where this file was the
* destination file. This value can specify the time of a completed, aborted, or failed copy
* attempt. This header does not appear if a copy is pending, if this file has never been
* the destination in a Copy File operation, or if this file has been modified after a
* concluded Copy File operation using Set File Properties, Put File, or Put Block List.
*/
Nullable<DateTime> CopyCompletedOn;
/**
* True if the file data and metadata are completely encrypted using the specified
* algorithm. Otherwise, the value is set to false (when the file is unencrypted, or if only
* parts of the file/application metadata are encrypted).
*/
bool IsServerEncrypted = bool();
/**
* The SMB related properties for the file.
*/
FileSmbProperties SmbProperties;
/**
* When a share is leased, specifies whether the lease is of infinite or fixed duration.
*/
Nullable<LeaseDurationType> LeaseDuration;
/**
* Lease state of the share.
*/
Nullable<Models::LeaseState> LeaseState;
/**
* The current lease status of the share.
*/
Nullable<Models::LeaseStatus> LeaseStatus;
/**
* The NFS related properties for the file.
*/
FilePosixProperties PosixProperties;
};
/**
* @brief Response type for #Azure::Storage::Files::Shares::ShareFileClient::Download.
*/
struct DownloadFileResult final
{
/**
* Content of the file or file range.
*/
std::unique_ptr<Core::IO::BodyStream> BodyStream;
/**
* Indicates the range of bytes returned.
*/
Core::Http::HttpRange ContentRange;
/**
* Size of the file in bytes.
*/
std::int64_t FileSize = std::int64_t();
/**
* MD5 hash for the downloaded range of data.
*/
Nullable<ContentHash> TransactionalContentHash;
/**
* Standard HTTP properties supported files.
*/
FileHttpHeaders HttpHeaders;
/**
* Detailed information of the downloaded file.
*/
DownloadFileDetails Details;
};
/**
* @brief The information returned when downloading a file to a destination.
*/
@ -317,6 +438,285 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
*/
Azure::Nullable<ShareFileHandleAccessRights> AccessRights;
};
/**
* @brief Response type for #Azure::Storage::Files::Shares::ShareFileClient::GetProperties.
*/
struct FileProperties final
{
/**
* The SMB related properties for the file.
*/
FileSmbProperties SmbProperties;
/**
* Standard HTTP properties supported files.
*/
FileHttpHeaders HttpHeaders;
/**
* Returns the date and time the file was last modified. The date format follows RFC 1123.
* Any operation that modifies the file or its properties updates the last modified time.
*/
DateTime LastModified;
/**
* A set of name-value pairs associated with this file as user-defined metadata.
*/
Core::CaseInsensitiveMap Metadata;
/**
* The size of the file in bytes. This header returns the value of the 'x-ms-content-length'
* header that is stored with the file.
*/
std::int64_t FileSize = std::int64_t();
/**
* The ETag contains a value that you can use to perform operations conditionally, in
* quotes.
*/
Azure::ETag ETag;
/**
* Conclusion time of the last attempted Copy File operation where this file was the
* destination file. This value can specify the time of a completed, aborted, or failed copy
* attempt.
*/
Nullable<DateTime> CopyCompletedOn;
/**
* Only appears when x-ms-copy-status is failed or pending. Describes cause of fatal or
* non-fatal copy operation failure.
*/
Nullable<std::string> CopyStatusDescription;
/**
* String identifier for the last attempted Copy File operation where this file was the
* destination file.
*/
Nullable<std::string> CopyId;
/**
* Contains the number of bytes copied and the total bytes in the source in the last
* attempted Copy File operation where this file was the destination file. Can show between
* 0 and Content-Length bytes copied.
*/
Nullable<std::string> CopyProgress;
/**
* URL up to 2KB in length that specifies the source file used in the last attempted Copy
* File operation where this file was the destination file.
*/
Nullable<std::string> CopySource;
/**
* State of the copy operation identified by 'x-ms-copy-id'.
*/
Nullable<Models::CopyStatus> CopyStatus;
/**
* The value of this header is set to true if the file data and application metadata are
* completely encrypted using the specified algorithm. Otherwise, the value is set to false
* (when the file is unencrypted, or if only parts of the file/application metadata are
* encrypted).
*/
bool IsServerEncrypted = bool();
/**
* When a file is leased, specifies whether the lease is of infinite or fixed duration.
*/
Nullable<LeaseDurationType> LeaseDuration;
/**
* Lease state of the file.
*/
Nullable<Models::LeaseState> LeaseState;
/**
* The current lease status of the file.
*/
Nullable<Models::LeaseStatus> LeaseStatus;
/**
* The NFS related properties for the file.
*/
FilePosixProperties PosixProperties;
};
/**
* @brief Response type for #Azure::Storage::Files::Shares::ShareFileClient::Create.
*/
struct CreateFileResult final
{
/**
* Indicates if the file was successfully created by this operation.
*/
bool Created = true;
/**
* The SMB related properties for the file.
*/
FileSmbProperties SmbProperties;
/**
* The ETag contains a value which represents the version of the file, in quotes.
*/
Azure::ETag ETag;
/**
* Returns the date and time the share was last modified. Any operation that modifies the
* directory or its properties updates the last modified time. Operations on files do not
* affect the last modified time of the directory.
*/
DateTime LastModified;
/**
* The value of this header is set to true if the contents of the request are successfully
* encrypted using the specified algorithm, and false otherwise.
*/
bool IsServerEncrypted = bool();
/**
* The NFS related properties for the file.
*/
FilePosixProperties PosixProperties;
};
/**
* @brief Response type for #Azure::Storage::Files::Shares::ShareFileClient::SetProperties.
*/
struct SetFilePropertiesResult final
{
/**
* The SMB related properties for the file.
*/
FileSmbProperties SmbProperties;
/**
* The ETag contains a value which represents the version of the file, in quotes.
*/
Azure::ETag ETag;
/**
* Returns the date and time the directory was last modified. Any operation that modifies
* the directory or its properties updates the last modified time. Operations on files do
* not affect the last modified time of the directory.
*/
DateTime LastModified;
/**
* The value of this header is set to true if the contents of the request are successfully
* encrypted using the specified algorithm, and false otherwise.
*/
bool IsServerEncrypted = bool();
/**
* The NFS related properties for the file.
*/
FilePosixProperties PosixProperties;
};
/**
* @brief Response type for #Azure::Storage::Files::Shares::ShareFileClient::CreateHardLink.
*/
struct CreateFileHardLinkResult final
{
/**
* The ETag contains a value which represents the version of the file, in quotes.
*/
Azure::ETag ETag;
/**
* Returns the date and time the share was last modified. Any operation that modifies the
* directory or its properties updates the last modified time. Operations on files do not
* affect the last modified time of the directory.
*/
DateTime LastModified;
/**
* The SMB related properties for the file.
*/
FileSmbProperties SmbProperties;
/**
* The NFS related properties for the file.
*/
FilePosixProperties PosixProperties;
};
/**
* @brief Response type for #Azure::Storage::Files::Shares::ShareDirectoryClient::Create.
*/
struct CreateDirectoryResult final
{
/**
* Indicates if the directory was successfully created by this operation.
*/
bool Created = true;
/**
* The SMB related properties for the file.
*/
FileSmbProperties SmbProperties;
/**
* The ETag contains a value which represents the version of the directory, in quotes.
*/
Azure::ETag ETag;
/**
* Returns the date and time the share was last modified. Any operation that modifies the
* directory or its properties updates the last modified time. Operations on files do not
* affect the last modified time of the directory.
*/
DateTime LastModified;
/**
* The value of this header is set to true if the contents of the request are successfully
* encrypted using the specified algorithm, and false otherwise.
*/
bool IsServerEncrypted = bool();
/**
* The NFS related properties for the file.
*/
FilePosixProperties PosixProperties;
};
/**
* @brief Response type for
* #Azure::Storage::Files::Shares::ShareDirectoryClient::GetProperties.
*/
struct DirectoryProperties final
{
/**
* The SMB related properties for the file.
*/
FileSmbProperties SmbProperties;
/**
* A set of name-value pairs that contain metadata for the directory.
*/
Core::CaseInsensitiveMap Metadata;
/**
* The ETag contains a value that you can use to perform operations conditionally, in
* quotes.
*/
Azure::ETag ETag;
/**
* Returns the date and time the Directory was last modified. Operations on files within the
* directory do not affect the last modified time of the directory.
*/
DateTime LastModified;
/**
* The value of this header is set to true if the directory metadata is completely encrypted
* using the specified algorithm. Otherwise, the value is set to false.
*/
bool IsServerEncrypted = bool();
/**
* The NFS related properties for the file.
*/
FilePosixProperties PosixProperties;
};
/**
* @brief Response type for
* #Azure::Storage::Files::Shares::ShareDirectoryClient::SetProperties.
*/
struct SetDirectoryPropertiesResult final
{
/**
* The SMB related properties for the file.
*/
FileSmbProperties SmbProperties;
/**
* The ETag contains a value which represents the version of the file, in quotes.
*/
Azure::ETag ETag;
/**
* Returns the date and time the directory was last modified. Any operation that modifies
* the directory or its properties updates the last modified time. Operations on files do
* not affect the last modified time of the directory.
*/
DateTime LastModified;
/**
* The value of this header is set to true if the contents of the request are successfully
* encrypted using the specified algorithm, and false otherwise.
*/
bool IsServerEncrypted = bool();
/**
* The NFS related properties for the file.
*/
FilePosixProperties PosixProperties;
};
} // namespace Models
/**

File diff suppressed because it is too large Load Diff

View File

@ -164,32 +164,20 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
auto protocolLayerOptions = _detail::DirectoryClient::CreateDirectoryOptions();
protocolLayerOptions.Metadata
= std::map<std::string, std::string>(options.Metadata.begin(), options.Metadata.end());
if (options.SmbProperties.Attributes.GetValues().empty())
{
protocolLayerOptions.FileAttributes = Models::FileAttributes::Directory.ToString();
}
else
{
protocolLayerOptions.FileAttributes = options.SmbProperties.Attributes.ToString();
}
protocolLayerOptions.FileAttributes = options.SmbProperties.Attributes.ToString();
if (options.SmbProperties.CreatedOn.HasValue())
{
protocolLayerOptions.FileCreationTime = options.SmbProperties.CreatedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileCreationTime = std::string(FileDefaultTimeValue);
}
if (options.SmbProperties.LastWrittenOn.HasValue())
{
protocolLayerOptions.FileLastWriteTime = options.SmbProperties.LastWrittenOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileLastWriteTime = std::string(FileDefaultTimeValue);
}
if (options.SmbProperties.ChangedOn.HasValue())
{
protocolLayerOptions.FileChangeTime = options.SmbProperties.ChangedOn.Value().ToString(
@ -203,13 +191,16 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
{
protocolLayerOptions.FilePermissionKey = options.SmbProperties.PermissionKey;
}
else
{
protocolLayerOptions.FilePermission = std::string(FileInheritPermission);
}
protocolLayerOptions.AllowTrailingDot = m_allowTrailingDot;
protocolLayerOptions.FileRequestIntent = m_shareTokenIntent;
protocolLayerOptions.FilePermissionFormat = options.DirectoryPermissionFormat;
if (options.PosixProperties.FileMode.HasValue())
{
protocolLayerOptions.FileMode = options.PosixProperties.FileMode.Value().ToOctalFileMode();
}
protocolLayerOptions.Owner = options.PosixProperties.Owner;
protocolLayerOptions.Group = options.PosixProperties.Group;
auto result = _detail::DirectoryClient::Create(
*m_pipeline, m_shareDirectoryUrl, protocolLayerOptions, context);
Models::CreateDirectoryResult ret;
@ -218,7 +209,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
ret.IsServerEncrypted = result.Value.IsServerEncrypted;
ret.LastModified = std::move(result.Value.LastModified);
ret.SmbProperties = std::move(result.Value.SmbProperties);
if (result.Value.FileMode.HasValue())
{
ret.PosixProperties.FileMode
= Models::NfsFileMode::ParseOctalFileMode(result.Value.FileMode.Value());
}
ret.PosixProperties.Owner = std::move(result.Value.Owner);
ret.PosixProperties.Group = std::move(result.Value.Group);
ret.PosixProperties.NfsFileType = std::move(result.Value.NfsFileType);
return Azure::Response<Models::CreateDirectoryResult>(
std::move(ret), std::move(result.RawResponse));
}
@ -417,8 +415,24 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
auto protocolLayerOptions = _detail::DirectoryClient::GetDirectoryPropertiesOptions();
protocolLayerOptions.AllowTrailingDot = m_allowTrailingDot;
protocolLayerOptions.FileRequestIntent = m_shareTokenIntent;
return _detail::DirectoryClient::GetProperties(
auto response = _detail::DirectoryClient::GetProperties(
*m_pipeline, m_shareDirectoryUrl, protocolLayerOptions, context);
Models::DirectoryProperties ret;
ret.ETag = std::move(response.Value.ETag);
ret.IsServerEncrypted = response.Value.IsServerEncrypted;
ret.LastModified = std::move(response.Value.LastModified);
ret.Metadata = std::move(response.Value.Metadata);
ret.SmbProperties = std::move(response.Value.SmbProperties);
if (response.Value.FileMode.HasValue())
{
ret.PosixProperties.FileMode
= Models::NfsFileMode::ParseOctalFileMode(response.Value.FileMode.Value());
}
ret.PosixProperties.Owner = std::move(response.Value.Owner);
ret.PosixProperties.Group = std::move(response.Value.Group);
ret.PosixProperties.NfsFileType = std::move(response.Value.NfsFileType);
return Azure::Response<Models::DirectoryProperties>(
std::move(ret), std::move(response.RawResponse));
}
Azure::Response<Models::SetDirectoryPropertiesResult> ShareDirectoryClient::SetProperties(
@ -428,28 +442,16 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
{
auto protocolLayerOptions = _detail::DirectoryClient::SetDirectoryPropertiesOptions();
protocolLayerOptions.FileAttributes = smbProperties.Attributes.ToString();
if (protocolLayerOptions.FileAttributes.empty())
{
protocolLayerOptions.FileAttributes = FilePreserveSmbProperties;
}
if (smbProperties.CreatedOn.HasValue())
{
protocolLayerOptions.FileCreationTime = smbProperties.CreatedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileCreationTime = FilePreserveSmbProperties;
}
if (smbProperties.LastWrittenOn.HasValue())
{
protocolLayerOptions.FileLastWriteTime = smbProperties.LastWrittenOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileLastWriteTime = FilePreserveSmbProperties;
}
if (smbProperties.ChangedOn.HasValue())
{
protocolLayerOptions.FileChangeTime = smbProperties.ChangedOn.Value().ToString(
@ -463,15 +465,31 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
{
protocolLayerOptions.FilePermissionKey = smbProperties.PermissionKey;
}
else
{
protocolLayerOptions.FilePermission = FilePreserveSmbProperties;
}
protocolLayerOptions.AllowTrailingDot = m_allowTrailingDot;
protocolLayerOptions.FileRequestIntent = m_shareTokenIntent;
protocolLayerOptions.FilePermissionFormat = options.FilePermissionFormat;
return _detail::DirectoryClient::SetProperties(
if (options.PosixProperties.FileMode.HasValue())
{
protocolLayerOptions.FileMode = options.PosixProperties.FileMode.Value().ToOctalFileMode();
}
protocolLayerOptions.Owner = options.PosixProperties.Owner;
protocolLayerOptions.Group = options.PosixProperties.Group;
auto response = _detail::DirectoryClient::SetProperties(
*m_pipeline, m_shareDirectoryUrl, protocolLayerOptions, context);
Models::SetDirectoryPropertiesResult ret;
ret.ETag = std::move(response.Value.ETag);
ret.IsServerEncrypted = response.Value.IsServerEncrypted;
ret.LastModified = std::move(response.Value.LastModified);
ret.SmbProperties = std::move(response.Value.SmbProperties);
if (response.Value.FileMode.HasValue())
{
ret.PosixProperties.FileMode
= Models::NfsFileMode::ParseOctalFileMode(response.Value.FileMode.Value());
}
ret.PosixProperties.Owner = std::move(response.Value.Owner);
ret.PosixProperties.Group = std::move(response.Value.Group);
return Azure::Response<Models::SetDirectoryPropertiesResult>(
std::move(ret), std::move(response.RawResponse));
}
Azure::Response<Models::SetDirectoryMetadataResult> ShareDirectoryClient::SetMetadata(

View File

@ -147,28 +147,17 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
protocolLayerOptions.Metadata
= std::map<std::string, std::string>(options.Metadata.begin(), options.Metadata.end());
protocolLayerOptions.FileAttributes = options.SmbProperties.Attributes.ToString();
if (protocolLayerOptions.FileAttributes.empty())
{
protocolLayerOptions.FileAttributes = Models::FileAttributes::None.ToString();
}
if (options.SmbProperties.CreatedOn.HasValue())
{
protocolLayerOptions.FileCreationTime = options.SmbProperties.CreatedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileCreationTime = std::string(FileDefaultTimeValue);
}
if (options.SmbProperties.LastWrittenOn.HasValue())
{
protocolLayerOptions.FileLastWriteTime = options.SmbProperties.LastWrittenOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileLastWriteTime = std::string(FileDefaultTimeValue);
}
if (options.SmbProperties.ChangedOn.HasValue())
{
protocolLayerOptions.FileChangeTime = options.SmbProperties.ChangedOn.Value().ToString(
@ -182,10 +171,6 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
{
protocolLayerOptions.FilePermissionKey = options.SmbProperties.PermissionKey;
}
else
{
protocolLayerOptions.FilePermission = std::string(FileInheritPermission);
}
protocolLayerOptions.FileContentLength = fileSize;
if (!options.HttpHeaders.ContentType.empty())
{
@ -218,6 +203,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
protocolLayerOptions.AllowTrailingDot = m_allowTrailingDot;
protocolLayerOptions.FileRequestIntent = m_shareTokenIntent;
protocolLayerOptions.FilePermissionFormat = options.FilePermissionFormat;
if (options.PosixProperties.FileMode.HasValue())
{
protocolLayerOptions.FileMode = options.PosixProperties.FileMode.Value().ToOctalFileMode();
}
protocolLayerOptions.Owner = options.PosixProperties.Owner;
protocolLayerOptions.Group = options.PosixProperties.Group;
protocolLayerOptions.NfsFileType = options.PosixProperties.NfsFileType;
auto result
= _detail::FileClient::Create(*m_pipeline, m_shareFileUrl, protocolLayerOptions, context);
Models::CreateFileResult ret;
@ -226,6 +218,14 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
ret.SmbProperties = std::move(result.Value.SmbProperties);
ret.IsServerEncrypted = result.Value.IsServerEncrypted;
ret.LastModified = std::move(result.Value.LastModified);
if (result.Value.FileMode.HasValue())
{
ret.PosixProperties.FileMode
= Models::NfsFileMode::ParseOctalFileMode(result.Value.FileMode.Value());
}
ret.PosixProperties.Owner = std::move(result.Value.Owner);
ret.PosixProperties.Group = std::move(result.Value.Group);
ret.PosixProperties.NfsFileType = std::move(result.Value.NfsFileType);
return Azure::Response<Models::CreateFileResult>(std::move(ret), std::move(result.RawResponse));
}
@ -242,6 +242,7 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
= _detail::FileClient::Delete(*m_pipeline, m_shareFileUrl, protocolLayerOptions, context);
Models::DeleteFileResult ret;
ret.Deleted = true;
ret.LinkCount = result.Value.LinkCount;
return Azure::Response<Models::DeleteFileResult>(std::move(ret), std::move(result.RawResponse));
}
@ -363,7 +364,37 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
= Azure::Core::Http::HttpRange{rangeStartOffset, rangeEndOffset - rangeStartOffset + 1};
downloadResponse.Value.FileSize = std::stoll(contentRange.substr(slash_pos + 1));
}
return downloadResponse;
Models::DownloadFileResult result;
result.BodyStream = std::move(downloadResponse.Value.BodyStream);
result.ContentRange = std::move(downloadResponse.Value.ContentRange);
result.FileSize = downloadResponse.Value.FileSize;
result.HttpHeaders = std::move(downloadResponse.Value.HttpHeaders);
result.TransactionalContentHash = std::move(downloadResponse.Value.TransactionalContentHash);
result.Details.CopyCompletedOn = std::move(downloadResponse.Value.Details.CopyCompletedOn);
result.Details.CopyId = std::move(downloadResponse.Value.Details.CopyId);
result.Details.CopyProgress = std::move(downloadResponse.Value.Details.CopyProgress);
result.Details.CopySource = std::move(downloadResponse.Value.Details.CopySource);
result.Details.CopyStatus = std::move(downloadResponse.Value.Details.CopyStatus);
result.Details.CopyStatusDescription
= std::move(downloadResponse.Value.Details.CopyStatusDescription);
result.Details.ETag = std::move(downloadResponse.Value.Details.ETag);
result.Details.IsServerEncrypted = downloadResponse.Value.Details.IsServerEncrypted;
result.Details.LastModified = std::move(downloadResponse.Value.Details.LastModified);
result.Details.LeaseDuration = std::move(downloadResponse.Value.Details.LeaseDuration);
result.Details.LeaseState = std::move(downloadResponse.Value.Details.LeaseState);
result.Details.LeaseStatus = std::move(downloadResponse.Value.Details.LeaseStatus);
result.Details.Metadata = std::move(downloadResponse.Value.Details.Metadata);
result.Details.SmbProperties = std::move(downloadResponse.Value.Details.SmbProperties);
if (downloadResponse.Value.Details.FileMode.HasValue())
{
result.Details.PosixProperties.FileMode = Models::NfsFileMode::ParseOctalFileMode(
downloadResponse.Value.Details.FileMode.Value());
}
result.Details.PosixProperties.Owner = std::move(downloadResponse.Value.Details.Owner);
result.Details.PosixProperties.Group = std::move(downloadResponse.Value.Details.Group);
result.Details.PosixProperties.LinkCount = std::move(downloadResponse.Value.Details.LinkCount);
return Azure::Response<Models::DownloadFileResult>(
std::move(result), std::move(downloadResponse.RawResponse));
}
StartFileCopyOperation ShareFileClient::StartCopy(
@ -375,67 +406,154 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
protocolLayerOptions.Metadata
= std::map<std::string, std::string>(options.Metadata.begin(), options.Metadata.end());
protocolLayerOptions.CopySource = std::move(copySource);
if (options.SmbProperties.Attributes.GetValues().empty())
if (options.SmbPropertiesToCopy.HasValue())
{
protocolLayerOptions.FileAttributes = FileCopySourceTime;
}
else
{
protocolLayerOptions.FileAttributes = options.SmbProperties.Attributes.ToString();
}
if (options.SmbProperties.CreatedOn.HasValue())
{
protocolLayerOptions.FileCreationTime = options.SmbProperties.CreatedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileCreationTime = std::string(FileCopySourceTime);
}
if (options.SmbProperties.LastWrittenOn.HasValue())
{
protocolLayerOptions.FileLastWriteTime = options.SmbProperties.LastWrittenOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileLastWriteTime = std::string(FileCopySourceTime);
}
if (options.SmbProperties.ChangedOn.HasValue())
{
protocolLayerOptions.FileChangeTime = options.SmbProperties.ChangedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
if (options.PermissionCopyMode.HasValue())
{
protocolLayerOptions.FilePermissionCopyMode = options.PermissionCopyMode.Value();
if (options.PermissionCopyMode.Value() == Models::PermissionCopyMode::Override)
if ((options.SmbPropertiesToCopy.Value() & CopyableFileSmbPropertyFlags::FileAttributes)
== CopyableFileSmbPropertyFlags::FileAttributes)
{
if (options.Permission.HasValue())
protocolLayerOptions.FileAttributes = FileCopySourceTime;
}
else if (!options.SmbProperties.Attributes.GetValues().empty())
{
protocolLayerOptions.FileAttributes = options.SmbProperties.Attributes.ToString();
}
if ((options.SmbPropertiesToCopy.Value() & CopyableFileSmbPropertyFlags::CreatedOn)
== CopyableFileSmbPropertyFlags::CreatedOn)
{
protocolLayerOptions.FileCreationTime = std::string(FileCopySourceTime);
}
else if (options.SmbProperties.CreatedOn.HasValue())
{
protocolLayerOptions.FileCreationTime = options.SmbProperties.CreatedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
if ((options.SmbPropertiesToCopy.Value() & CopyableFileSmbPropertyFlags::LastWrittenOn)
== CopyableFileSmbPropertyFlags::LastWrittenOn)
{
protocolLayerOptions.FileLastWriteTime = std::string(FileCopySourceTime);
}
else if (options.SmbProperties.LastWrittenOn.HasValue())
{
protocolLayerOptions.FileLastWriteTime
= options.SmbProperties.LastWrittenOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
if ((options.SmbPropertiesToCopy.Value() & CopyableFileSmbPropertyFlags::ChangedOn)
== CopyableFileSmbPropertyFlags::ChangedOn)
{
protocolLayerOptions.FileChangeTime = std::string(FileCopySourceTime);
}
else if (options.SmbProperties.ChangedOn.HasValue())
{
protocolLayerOptions.FileChangeTime = options.SmbProperties.ChangedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
if ((options.SmbPropertiesToCopy.Value() & CopyableFileSmbPropertyFlags::Permission)
== CopyableFileSmbPropertyFlags::Permission)
{
protocolLayerOptions.FilePermissionCopyMode = Models::PermissionCopyMode::Source;
}
else if (options.PermissionCopyMode.HasValue())
{
protocolLayerOptions.FilePermissionCopyMode = options.PermissionCopyMode.Value();
if (options.PermissionCopyMode.Value() == Models::PermissionCopyMode::Override)
{
protocolLayerOptions.FilePermission = options.Permission;
protocolLayerOptions.FilePermissionFormat = options.FilePermissionFormat;
}
else if (options.SmbProperties.PermissionKey.HasValue())
{
protocolLayerOptions.FilePermissionKey = options.SmbProperties.PermissionKey;
}
else
{
AZURE_ASSERT_MSG(false, "Either FilePermission or FilePermissionKey must be set.");
if (options.Permission.HasValue())
{
protocolLayerOptions.FilePermission = options.Permission;
protocolLayerOptions.FilePermissionFormat = options.FilePermissionFormat;
}
else if (options.SmbProperties.PermissionKey.HasValue())
{
protocolLayerOptions.FilePermissionKey = options.SmbProperties.PermissionKey;
}
else
{
AZURE_ASSERT_MSG(false, "Either FilePermission or FilePermissionKey must be set.");
}
}
}
}
else
{
protocolLayerOptions.FilePermissionCopyMode = Models::PermissionCopyMode::Source;
if (options.SmbProperties.Attributes.GetValues().empty())
{
protocolLayerOptions.FileAttributes = FileCopySourceTime;
}
else
{
protocolLayerOptions.FileAttributes = options.SmbProperties.Attributes.ToString();
}
if (options.SmbProperties.CreatedOn.HasValue())
{
protocolLayerOptions.FileCreationTime = options.SmbProperties.CreatedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileCreationTime = std::string(FileCopySourceTime);
}
if (options.SmbProperties.LastWrittenOn.HasValue())
{
protocolLayerOptions.FileLastWriteTime
= options.SmbProperties.LastWrittenOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileLastWriteTime = std::string(FileCopySourceTime);
}
if (options.SmbProperties.ChangedOn.HasValue())
{
protocolLayerOptions.FileChangeTime = options.SmbProperties.ChangedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
if (options.PermissionCopyMode.HasValue())
{
protocolLayerOptions.FilePermissionCopyMode = options.PermissionCopyMode.Value();
if (options.PermissionCopyMode.Value() == Models::PermissionCopyMode::Override)
{
if (options.Permission.HasValue())
{
protocolLayerOptions.FilePermission = options.Permission;
protocolLayerOptions.FilePermissionFormat = options.FilePermissionFormat;
}
else if (options.SmbProperties.PermissionKey.HasValue())
{
protocolLayerOptions.FilePermissionKey = options.SmbProperties.PermissionKey;
}
else
{
AZURE_ASSERT_MSG(false, "Either FilePermission or FilePermissionKey must be set.");
}
}
}
else
{
protocolLayerOptions.FilePermissionCopyMode = Models::PermissionCopyMode::Source;
}
}
protocolLayerOptions.IgnoreReadOnly = options.IgnoreReadOnly;
protocolLayerOptions.SetArchiveAttribute = options.SetArchiveAttribute;
protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId;
protocolLayerOptions.AllowTrailingDot = m_allowTrailingDot;
protocolLayerOptions.AllowSourceTrailingDot = m_allowSourceTrailingDot;
protocolLayerOptions.FileRequestIntent = m_shareTokenIntent;
if (options.PosixProperties.FileMode.HasValue())
{
protocolLayerOptions.FileMode = options.PosixProperties.FileMode.Value().ToOctalFileMode();
}
protocolLayerOptions.FileModeCopyMode = options.ModeCopyMode;
protocolLayerOptions.Owner = options.PosixProperties.Owner;
protocolLayerOptions.Group = options.PosixProperties.Group;
protocolLayerOptions.FileOwnerCopyMode = options.OwnerCopyMode;
auto response = _detail::FileClient::StartCopy(
*m_pipeline, m_shareFileUrl, protocolLayerOptions, context);
@ -467,8 +585,35 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId;
protocolLayerOptions.AllowTrailingDot = m_allowTrailingDot;
protocolLayerOptions.FileRequestIntent = m_shareTokenIntent;
return _detail::FileClient::GetProperties(
auto response = _detail::FileClient::GetProperties(
*m_pipeline, m_shareFileUrl, protocolLayerOptions, context);
Models::FileProperties ret;
ret.CopyCompletedOn = std::move(response.Value.CopyCompletedOn);
ret.CopyId = std::move(response.Value.CopyId);
ret.CopyProgress = std::move(response.Value.CopyProgress);
ret.CopySource = std::move(response.Value.CopySource);
ret.CopyStatus = std::move(response.Value.CopyStatus);
ret.CopyStatusDescription = std::move(response.Value.CopyStatusDescription);
ret.ETag = std::move(response.Value.ETag);
ret.FileSize = response.Value.FileSize;
ret.HttpHeaders = std::move(response.Value.HttpHeaders);
ret.IsServerEncrypted = response.Value.IsServerEncrypted;
ret.LastModified = std::move(response.Value.LastModified);
ret.LeaseDuration = std::move(response.Value.LeaseDuration);
ret.LeaseState = std::move(response.Value.LeaseState);
ret.LeaseStatus = std::move(response.Value.LeaseStatus);
ret.Metadata = std::move(response.Value.Metadata);
ret.SmbProperties = std::move(response.Value.SmbProperties);
if (response.Value.FileMode.HasValue())
{
ret.PosixProperties.FileMode
= Models::NfsFileMode::ParseOctalFileMode(response.Value.FileMode.Value());
}
ret.PosixProperties.Owner = std::move(response.Value.Owner);
ret.PosixProperties.Group = std::move(response.Value.Group);
ret.PosixProperties.NfsFileType = std::move(response.Value.NfsFileType);
ret.PosixProperties.LinkCount = std::move(response.Value.LinkCount);
return Azure::Response<Models::FileProperties>(std::move(ret), std::move(response.RawResponse));
}
Azure::Response<Models::SetFilePropertiesResult> ShareFileClient::SetProperties(
@ -479,28 +624,16 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
{
auto protocolLayerOptions = _detail::FileClient::SetFileHttpHeadersOptions();
protocolLayerOptions.FileAttributes = smbProperties.Attributes.ToString();
if (protocolLayerOptions.FileAttributes.empty())
{
protocolLayerOptions.FileAttributes = FilePreserveSmbProperties;
}
if (smbProperties.CreatedOn.HasValue())
{
protocolLayerOptions.FileCreationTime = smbProperties.CreatedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileCreationTime = FilePreserveSmbProperties;
}
if (smbProperties.LastWrittenOn.HasValue())
{
protocolLayerOptions.FileLastWriteTime = smbProperties.LastWrittenOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileLastWriteTime = FilePreserveSmbProperties;
}
if (smbProperties.ChangedOn.HasValue())
{
protocolLayerOptions.FileChangeTime = smbProperties.ChangedOn.Value().ToString(
@ -516,10 +649,6 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
{
protocolLayerOptions.FilePermissionKey = smbProperties.PermissionKey;
}
else
{
protocolLayerOptions.FilePermission = FilePreserveSmbProperties;
}
if (!httpHeaders.ContentType.empty())
{
@ -544,9 +673,31 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
protocolLayerOptions.AllowTrailingDot = m_allowTrailingDot;
protocolLayerOptions.FileRequestIntent = m_shareTokenIntent;
protocolLayerOptions.FilePermissionFormat = options.FilePermissionFormat;
if (options.PosixProperties.FileMode.HasValue())
{
protocolLayerOptions.FileMode = options.PosixProperties.FileMode.Value().ToOctalFileMode();
}
protocolLayerOptions.Owner = options.PosixProperties.Owner;
protocolLayerOptions.Group = options.PosixProperties.Group;
return _detail::FileClient::SetHttpHeaders(
auto response = _detail::FileClient::SetHttpHeaders(
*m_pipeline, m_shareFileUrl, protocolLayerOptions, context);
Models::SetFilePropertiesResult ret;
ret.ETag = std::move(response.Value.ETag);
ret.IsServerEncrypted = response.Value.IsServerEncrypted;
ret.LastModified = std::move(response.Value.LastModified);
ret.SmbProperties = std::move(response.Value.SmbProperties);
if (response.Value.FileMode.HasValue())
{
ret.PosixProperties.FileMode
= Models::NfsFileMode::ParseOctalFileMode(response.Value.FileMode.Value());
}
ret.PosixProperties.Owner = std::move(response.Value.Owner);
ret.PosixProperties.Group = std::move(response.Value.Group);
ret.PosixProperties.LinkCount = std::move(response.Value.LinkCount);
return Azure::Response<Models::SetFilePropertiesResult>(
std::move(ret), std::move(response.RawResponse));
}
Azure::Response<Models::SetFileMetadataResult> ShareFileClient::SetMetadata(
@ -1014,28 +1165,19 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
_detail::FileClient::CreateFileOptions protocolLayerOptions;
protocolLayerOptions.FileContentLength = bufferSize;
protocolLayerOptions.FileAttributes = options.SmbProperties.Attributes.ToString();
if (protocolLayerOptions.FileAttributes.empty())
{
protocolLayerOptions.FileAttributes = Models::FileAttributes::None.ToString();
}
if (options.SmbProperties.CreatedOn.HasValue())
{
protocolLayerOptions.FileCreationTime = options.SmbProperties.CreatedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileCreationTime = std::string(FileDefaultTimeValue);
}
if (options.SmbProperties.LastWrittenOn.HasValue())
{
protocolLayerOptions.FileLastWriteTime = options.SmbProperties.LastWrittenOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileLastWriteTime = std::string(FileDefaultTimeValue);
}
if (options.SmbProperties.ChangedOn.HasValue())
{
protocolLayerOptions.FileChangeTime = options.SmbProperties.ChangedOn.Value().ToString(
@ -1049,10 +1191,6 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
{
protocolLayerOptions.FilePermissionKey = options.SmbProperties.PermissionKey;
}
else
{
protocolLayerOptions.FilePermission = std::string(FileInheritPermission);
}
if (!options.HttpHeaders.ContentType.empty())
{
@ -1086,6 +1224,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
protocolLayerOptions.AllowTrailingDot = m_allowTrailingDot;
protocolLayerOptions.FileRequestIntent = m_shareTokenIntent;
protocolLayerOptions.FilePermissionFormat = options.FilePermissionFormat;
if (options.PosixProperties.FileMode.HasValue())
{
protocolLayerOptions.FileMode = options.PosixProperties.FileMode.Value().ToOctalFileMode();
}
protocolLayerOptions.Owner = options.PosixProperties.Owner;
protocolLayerOptions.Group = options.PosixProperties.Group;
protocolLayerOptions.NfsFileType = options.PosixProperties.NfsFileType;
auto createResult
= _detail::FileClient::Create(*m_pipeline, m_shareFileUrl, protocolLayerOptions, context);
@ -1132,28 +1277,19 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
_detail::FileClient::CreateFileOptions protocolLayerOptions;
protocolLayerOptions.FileContentLength = fileReader.GetFileSize();
protocolLayerOptions.FileAttributes = options.SmbProperties.Attributes.ToString();
if (protocolLayerOptions.FileAttributes.empty())
{
protocolLayerOptions.FileAttributes = Models::FileAttributes::None.ToString();
}
if (options.SmbProperties.CreatedOn.HasValue())
{
protocolLayerOptions.FileCreationTime = options.SmbProperties.CreatedOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileCreationTime = std::string(FileDefaultTimeValue);
}
if (options.SmbProperties.LastWrittenOn.HasValue())
{
protocolLayerOptions.FileLastWriteTime = options.SmbProperties.LastWrittenOn.Value().ToString(
Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits);
}
else
{
protocolLayerOptions.FileLastWriteTime = std::string(FileDefaultTimeValue);
}
if (options.SmbProperties.ChangedOn.HasValue())
{
protocolLayerOptions.FileChangeTime = options.SmbProperties.ChangedOn.Value().ToString(
@ -1167,10 +1303,6 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
{
protocolLayerOptions.FilePermissionKey = options.SmbProperties.PermissionKey;
}
else
{
protocolLayerOptions.FilePermission = std::string(FileInheritPermission);
}
if (!options.HttpHeaders.ContentType.empty())
{
@ -1204,6 +1336,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
protocolLayerOptions.AllowTrailingDot = m_allowTrailingDot;
protocolLayerOptions.FileRequestIntent = m_shareTokenIntent;
protocolLayerOptions.FilePermissionFormat = options.FilePermissionFormat;
if (options.PosixProperties.FileMode.HasValue())
{
protocolLayerOptions.FileMode = options.PosixProperties.FileMode.Value().ToOctalFileMode();
}
protocolLayerOptions.Owner = options.PosixProperties.Owner;
protocolLayerOptions.Group = options.PosixProperties.Group;
protocolLayerOptions.NfsFileType = options.PosixProperties.NfsFileType;
auto createResult
= _detail::FileClient::Create(*m_pipeline, m_shareFileUrl, protocolLayerOptions, context);
@ -1294,4 +1433,30 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
return _detail::FileClient::UploadRangeFromUri(
*m_pipeline, m_shareFileUrl, protocolLayerOptions, context);
}
Azure::Response<Models::CreateFileHardLinkResult> ShareFileClient::CreateHardLink(
const std::string& targetFile,
const CreateHardLinkOptions& options,
const Azure::Core::Context& context) const
{
_detail::FileClient::CreateFileHardLinkOptions protocolLayerOptions;
protocolLayerOptions.TargetFile = targetFile;
protocolLayerOptions.FileRequestIntent = m_shareTokenIntent;
protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId;
auto response = _detail::FileClient::CreateHardLink(
*m_pipeline, m_shareFileUrl, protocolLayerOptions, context);
Models::CreateFileHardLinkResult ret;
ret.ETag = std::move(response.Value.ETag);
ret.SmbProperties = std::move(response.Value.SmbProperties);
ret.LastModified = std::move(response.Value.LastModified);
ret.PosixProperties.FileMode = Models::NfsFileMode::ParseOctalFileMode(response.Value.FileMode);
ret.PosixProperties.Owner = std::move(response.Value.Owner);
ret.PosixProperties.Group = std::move(response.Value.Group);
ret.PosixProperties.NfsFileType = std::move(response.Value.NfsFileType);
ret.PosixProperties.LinkCount = response.Value.LinkCount;
return Azure::Response<Models::CreateFileHardLinkResult>(
std::move(ret), std::move(response.RawResponse));
}
}}}} // namespace Azure::Storage::Files::Shares

View File

@ -7,4 +7,223 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
const ShareAudience ShareAudience::DefaultAudience(_internal::StorageDefaultAudience);
namespace Models {
namespace {
RolePermissions ParseOctal(char c)
{
RolePermissions permissions = RolePermissions::None;
int permissionValue = c - '0';
if (permissionValue < 0 || permissionValue > 7)
{
throw std::invalid_argument("Permission value must be >0 and <7.");
}
if ((permissionValue & 4) == 4)
{
permissions = permissions | RolePermissions::Read;
}
if ((permissionValue & 2) == 2)
{
permissions = permissions | RolePermissions::Write;
}
if ((permissionValue & 1) == 1)
{
permissions = permissions | RolePermissions::Execute;
}
return permissions;
}
char ToOctal(RolePermissions permissions)
{
char c = '0';
if ((permissions & RolePermissions::Read) == RolePermissions::Read)
{
c += 4;
}
if ((permissions & RolePermissions::Write) == RolePermissions::Write)
{
c += 2;
}
if ((permissions & RolePermissions::Execute) == RolePermissions::Execute)
{
c += 1;
}
return c;
}
RolePermissions ParseSymbolic(std::string s, bool& setSticky)
{
if (s.length() != 3)
{
throw std::invalid_argument("Symbolic role permission format is invalid.");
}
RolePermissions permissions = RolePermissions::None;
setSticky = false;
// Read character
if (s[0] == 'r')
{
permissions = permissions | RolePermissions ::Read;
}
else if (s[0] != '-')
{
throw std::invalid_argument(
"Invalid character in symbolic role permission: " + std::string(1, s[0]));
}
// Write character
if (s[1] == 'w')
{
permissions = permissions | RolePermissions ::Write;
}
else if (s[1] != '-')
{
throw std::invalid_argument(
"Invalid character in symbolic role permission: " + std::string(1, s[1]));
}
// Execute character
if (s[2] == 'x' || s[2] == 's' || s[2] == 't')
{
permissions = permissions | RolePermissions ::Execute;
if (s[2] == 's' || s[2] == 't')
{
setSticky = true;
}
}
if (s[2] == 'S' || s[2] == 'T')
{
setSticky = true;
}
if (s[2] != 'x' && s[2] != 's' && s[2] != 'S' && s[2] != 't' && s[2] != 'T' && s[2] != '-')
{
throw std::invalid_argument(
"Invalid character in symbolic role permission: " + std::string(1, s[2]));
}
return permissions;
}
std::string ToSymbolic(RolePermissions permissions)
{
std::string s;
s.push_back((permissions & RolePermissions::Read) == RolePermissions::Read ? 'r' : '-');
s.push_back((permissions & RolePermissions::Write) == RolePermissions::Write ? 'w' : '-');
s.push_back(
(permissions & RolePermissions::Execute) == RolePermissions::Execute ? 'x' : '-');
return s;
}
} // namespace
std::string NfsFileMode::ToOctalFileMode() const
{
int higherOrderDigit = 0;
if (EffectiveUserIdentity)
{
higherOrderDigit |= 4;
}
if (EffectiveGroupIdentity)
{
higherOrderDigit |= 2;
}
if (StickyBit)
{
higherOrderDigit |= 1;
}
std::string modeString = "";
modeString.push_back(static_cast<char>(higherOrderDigit + '0'));
modeString.push_back(ToOctal(Owner));
modeString.push_back(ToOctal(Group));
modeString.push_back(ToOctal(Other));
return modeString;
}
std::string NfsFileMode::ToSymbolicFileMode() const
{
std::string modeString = "";
modeString.append(ToSymbolic(Owner));
modeString.append(ToSymbolic(Group));
modeString.append(ToSymbolic(Other));
if (EffectiveUserIdentity)
{
if (modeString[2] == 'x')
{
modeString[2] = 's';
}
else
{
modeString[2] = 'S';
}
}
if (EffectiveGroupIdentity)
{
if (modeString[5] == 'x')
{
modeString[5] = 's';
}
else
{
modeString[5] = 'S';
}
}
if (StickyBit)
{
if (modeString[8] == 'x')
{
modeString[8] = 't';
}
else
{
modeString[8] = 'T';
}
}
return modeString;
}
NfsFileMode NfsFileMode::ParseOctalFileMode(const std::string& modeString)
{
if (modeString.length() != 4)
{
throw std::invalid_argument("modeString must be a 4-digit octal number.");
}
NfsFileMode mode;
mode.Owner = ParseOctal(modeString[1]);
mode.Group = ParseOctal(modeString[2]);
mode.Other = ParseOctal(modeString[3]);
int value = modeString[0] - '0';
if ((value & 4) == 4)
{
mode.EffectiveUserIdentity = true;
}
if ((value & 2) == 2)
{
mode.EffectiveGroupIdentity = true;
}
if ((value & 1) == 1)
{
mode.StickyBit = true;
}
return mode;
}
NfsFileMode NfsFileMode::ParseSymbolicFileMode(const std::string& modeString)
{
if (modeString.length() != 9)
{
throw std::invalid_argument("modeString must be a 9-character octal number.");
}
NfsFileMode mode;
mode.Owner = ParseSymbolic(modeString.substr(0, 3), mode.EffectiveUserIdentity);
mode.Group = ParseSymbolic(modeString.substr(3, 3), mode.EffectiveGroupIdentity);
mode.Other = ParseSymbolic(modeString.substr(6, 3), mode.StickyBit);
return mode;
}
} // namespace Models
}}}} // namespace Azure::Storage::Files::Shares

View File

@ -10,6 +10,7 @@
namespace Azure { namespace Storage { namespace Files { namespace Shares {
namespace Models {
ShareFileHandleAccessRights::ShareFileHandleAccessRights(const std::string& value)
{
if (!value.empty())

View File

@ -9,7 +9,7 @@ package-name: azure-storage-files-shares
namespace: Azure::Storage::Files::Shares
output-folder: generated
clear-output-folder: true
input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/storage/data-plane/Microsoft.FileStorage/stable/2025-01-05/file.json
input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/refs/heads/feature/storage/stg97base/specification/storage/data-plane/Microsoft.FileStorage/stable/2025-05-05/file.json
```
## ModelFour Options
@ -36,19 +36,20 @@ directive:
delete $["x-ms-code-generation-settings"];
```
### Delete Unused Query Parameters and Headers
### Delete Unused Query Parameters and Headers and global changes for Parameters and Headers
```yaml
directive:
- from: swagger-document
where: $["x-ms-paths"].*.*.parameters
transform: >
$ = $.filter(p => !(p["$ref"] && (p["$ref"].endsWith("#/parameters/Timeout") || p["$ref"].endsWith("#/parameters/ClientRequestId"))));
$ = $.filter(p => !(p["$ref"] && (p["$ref"].endsWith("#/parameters/Timeout") || p["$ref"].endsWith("#/parameters/ClientRequestId")
|| p["$ref"].endsWith("#/parameters/StructuredBodyGet") || p["$ref"].endsWith("#/parameters/StructuredBodyPut") || p["$ref"].endsWith("#/parameters/StructuredContentLength"))));
- from: swagger-document
where: $["x-ms-paths"].*.*.responses.*.headers
transform: >
for (const h in $) {
if (["x-ms-client-request-id", "x-ms-request-id", "x-ms-version", "Date"].includes(h)) {
if (["x-ms-client-request-id", "x-ms-request-id", "x-ms-version", "Date", "x-ms-structured-body", "x-ms-structured-content-length"].includes(h)) {
delete $[h];
}
}
@ -79,12 +80,12 @@ directive:
"name": "ApiVersion",
"modelAsString": false
},
"enum": ["2025-01-05"]
"enum": ["2025-05-05"]
};
- from: swagger-document
where: $.parameters
transform: >
$.ApiVersionParameter.enum[0] = "2025-01-05";
$.ApiVersionParameter.enum[0] = "2025-05-05";
```
### Rename Operations
@ -167,6 +168,9 @@ directive:
"File_ForceCloseHandles",
"Directory_Rename",
"File_Rename",
"File_CreateSymbolicLink",
"File_GetSymbolicLink",
"File_CreateHardLink",
];
for (const url in $["x-ms-paths"]) {
for (const verb in $["x-ms-paths"][url]) {
@ -229,6 +233,7 @@ directive:
$.FileLastWriteTimeMode["x-ms-enum"]["values"] = [{"value": "now", "name": "Now"},{"value": "preserve", "name": "Preserve"}];
$.FileRequestIntent["x-ms-enum"]["values"] = [{"value": "__placeHolder", "name": "__placeHolder"}, {"value": "backup", "name": "Backup"}];
$.FilePermissionFormat["enum"] = ["sddl", "binary"];
$.FileAttributes["required"] = true;
- from: swagger-document
where: $.definitions
transform: >
@ -658,11 +663,17 @@ directive:
transform: >
$.headers["x-ms-file-permission-key"]["x-ms-client-path"] = "SmbProperties.PermissionKey";
$.headers["x-ms-file-attributes"]["x-ms-client-path"] = "SmbProperties.Attributes";
$.headers["x-ms-file-attributes"]["x-nullable"] = true;
$.headers["x-ms-file-attributes"]["x-ms-client-default"] = "None";
$.headers["x-ms-file-creation-time"]["x-ms-client-path"] = "SmbProperties.CreatedOn";
$.headers["x-ms-file-last-write-time"]["x-ms-client-path"] = "SmbProperties.LastWrittenOn";
$.headers["x-ms-file-change-time"]["x-ms-client-path"] = "SmbProperties.ChangedOn";
$.headers["x-ms-file-id"]["x-ms-client-path"] = "SmbProperties.FileId";
$.headers["x-ms-file-parent-id"]["x-ms-client-path"] = "SmbProperties.ParentFileId";
$.headers["x-ms-mode"]["x-nullable"] = true;
$.headers["x-ms-owner"]["x-nullable"] = true;
$.headers["x-ms-group"]["x-nullable"] = true;
$.headers["x-ms-file-file-type"]["x-nullable"] = true;
$.schema = {
"type": "object",
"x-ms-client-name": "CreateDirectoryResult",
@ -670,7 +681,8 @@ directive:
"properties": {
"Created": {"type": "boolean", "x-ms-client-default": true, "x-ms-xml": {"name": ""}},
"SmbProperties": {"$ref": "#/definitions/FileSmbProperties", "x-ms-xml": {"name": ""}}
}
},
"x-namespace" : "_detail"
};
```
@ -700,18 +712,25 @@ directive:
transform: >
$.headers["x-ms-file-permission-key"]["x-ms-client-path"] = "SmbProperties.PermissionKey";
$.headers["x-ms-file-attributes"]["x-ms-client-path"] = "SmbProperties.Attributes";
$.headers["x-ms-file-attributes"]["x-nullable"] = true;
$.headers["x-ms-file-attributes"]["x-ms-client-default"] = "None";
$.headers["x-ms-file-creation-time"]["x-ms-client-path"] = "SmbProperties.CreatedOn";
$.headers["x-ms-file-last-write-time"]["x-ms-client-path"] = "SmbProperties.LastWrittenOn";
$.headers["x-ms-file-change-time"]["x-ms-client-path"] = "SmbProperties.ChangedOn";
$.headers["x-ms-file-id"]["x-ms-client-path"] = "SmbProperties.FileId";
$.headers["x-ms-file-parent-id"]["x-ms-client-path"] = "SmbProperties.ParentFileId";
$.headers["x-ms-mode"]["x-nullable"] = true;
$.headers["x-ms-owner"]["x-nullable"] = true;
$.headers["x-ms-group"]["x-nullable"] = true;
$.headers["x-ms-file-file-type"]["x-nullable"] = true;
$.schema = {
"type": "object",
"x-ms-client-name": "DirectoryProperties",
"x-ms-sealed": false,
"properties": {
"SmbProperties": {"$ref": "#/definitions/FileSmbProperties", "x-ms-xml": {"name": ""}}
}
},
"x-namespace" : "_detail"
};
```
@ -724,18 +743,24 @@ directive:
transform: >
$.headers["x-ms-file-permission-key"]["x-ms-client-path"] = "SmbProperties.PermissionKey";
$.headers["x-ms-file-attributes"]["x-ms-client-path"] = "SmbProperties.Attributes";
$.headers["x-ms-file-attributes"]["x-nullable"] = true;
$.headers["x-ms-file-attributes"]["x-ms-client-default"] = "None";
$.headers["x-ms-file-creation-time"]["x-ms-client-path"] = "SmbProperties.CreatedOn";
$.headers["x-ms-file-last-write-time"]["x-ms-client-path"] = "SmbProperties.LastWrittenOn";
$.headers["x-ms-file-change-time"]["x-ms-client-path"] = "SmbProperties.ChangedOn";
$.headers["x-ms-file-id"]["x-ms-client-path"] = "SmbProperties.FileId";
$.headers["x-ms-file-parent-id"]["x-ms-client-path"] = "SmbProperties.ParentFileId";
$.headers["x-ms-mode"]["x-nullable"] = true;
$.headers["x-ms-owner"]["x-nullable"] = true;
$.headers["x-ms-group"]["x-nullable"] = true;
$.schema = {
"type": "object",
"x-ms-client-name": "SetDirectoryPropertiesResult",
"x-ms-sealed": false,
"properties": {
"SmbProperties": {"$ref": "#/definitions/FileSmbProperties", "x-ms-xml": {"name": ""}}
}
},
"x-namespace" : "_detail"
};
```
@ -748,11 +773,17 @@ directive:
transform: >
$.headers["x-ms-file-permission-key"]["x-ms-client-path"] = "SmbProperties.PermissionKey";
$.headers["x-ms-file-attributes"]["x-ms-client-path"] = "SmbProperties.Attributes";
$.headers["x-ms-file-attributes"]["x-nullable"] = true;
$.headers["x-ms-file-attributes"]["x-ms-client-default"] = "None";
$.headers["x-ms-file-creation-time"]["x-ms-client-path"] = "SmbProperties.CreatedOn";
$.headers["x-ms-file-last-write-time"]["x-ms-client-path"] = "SmbProperties.LastWrittenOn";
$.headers["x-ms-file-change-time"]["x-ms-client-path"] = "SmbProperties.ChangedOn";
$.headers["x-ms-file-id"]["x-ms-client-path"] = "SmbProperties.FileId";
$.headers["x-ms-file-parent-id"]["x-ms-client-path"] = "SmbProperties.ParentFileId";
$.headers["x-ms-mode"]["x-nullable"] = true;
$.headers["x-ms-owner"]["x-nullable"] = true;
$.headers["x-ms-group"]["x-nullable"] = true;
$.headers["x-ms-file-file-type"]["x-nullable"] = true;
$.schema = {
"type": "object",
"x-ms-client-name": "CreateFileResult",
@ -760,7 +791,8 @@ directive:
"properties": {
"Created": {"type": "boolean", "x-ms-client-default": true, "x-ms-xml": {"name": ""}},
"SmbProperties": {"$ref": "#/definitions/FileSmbProperties", "x-ms-xml": {"name": ""}}
}
},
"x-namespace" : "_detail"
};
```
@ -773,6 +805,8 @@ directive:
transform: >
$.headers["x-ms-file-permission-key"]["x-ms-client-path"] = "SmbProperties.PermissionKey";
$.headers["x-ms-file-attributes"]["x-ms-client-path"] = "SmbProperties.Attributes";
$.headers["x-ms-file-attributes"]["x-nullable"] = true;
$.headers["x-ms-file-attributes"]["x-ms-client-default"] = "None";
$.headers["x-ms-file-creation-time"]["x-ms-client-path"] = "SmbProperties.CreatedOn";
$.headers["x-ms-file-last-write-time"]["x-ms-client-path"] = "SmbProperties.LastWrittenOn";
$.headers["x-ms-file-change-time"]["x-ms-client-path"] = "SmbProperties.ChangedOn";
@ -801,6 +835,11 @@ directive:
$.headers["x-ms-lease-duration"]["x-nullable"] = true;
$.headers["x-ms-lease-state"]["x-nullable"] = true;
$.headers["x-ms-lease-status"]["x-nullable"] = true;
$.headers["x-ms-mode"]["x-nullable"] = true;
$.headers["x-ms-owner"]["x-nullable"] = true;
$.headers["x-ms-group"]["x-nullable"] = true;
$.headers["x-ms-file-file-type"]["x-nullable"] = true;
$.headers["x-ms-link-count"]["x-nullable"] = true;
delete $.headers["x-ms-type"];
$.schema = {
"type": "object",
@ -809,7 +848,8 @@ directive:
"properties": {
"SmbProperties": {"$ref": "#/definitions/FileSmbProperties", "x-ms-xml": {"name": ""}},
"HttpHeaders": {"$ref": "#/definitions/FileHttpHeaders", "x-ms-xml": {"name": ""}}
}
},
"x-namespace" : "_detail"
};
```
@ -822,18 +862,25 @@ directive:
transform: >
$.headers["x-ms-file-permission-key"]["x-ms-client-path"] = "SmbProperties.PermissionKey";
$.headers["x-ms-file-attributes"]["x-ms-client-path"] = "SmbProperties.Attributes";
$.headers["x-ms-file-attributes"]["x-nullable"] = true;
$.headers["x-ms-file-attributes"]["x-ms-client-default"] = "None";
$.headers["x-ms-file-creation-time"]["x-ms-client-path"] = "SmbProperties.CreatedOn";
$.headers["x-ms-file-last-write-time"]["x-ms-client-path"] = "SmbProperties.LastWrittenOn";
$.headers["x-ms-file-change-time"]["x-ms-client-path"] = "SmbProperties.ChangedOn";
$.headers["x-ms-file-id"]["x-ms-client-path"] = "SmbProperties.FileId";
$.headers["x-ms-file-parent-id"]["x-ms-client-path"] = "SmbProperties.ParentFileId";
$.headers["x-ms-mode"]["x-nullable"] = true;
$.headers["x-ms-owner"]["x-nullable"] = true;
$.headers["x-ms-group"]["x-nullable"] = true;
$.headers["x-ms-link-count"]["x-nullable"] = true;
$.schema = {
"type": "object",
"x-ms-client-name": "SetFilePropertiesResult",
"x-ms-sealed": false,
"properties": {
"SmbProperties": {"$ref": "#/definitions/FileSmbProperties", "x-ms-xml": {"name": ""}}
}
},
"x-namespace" : "_detail"
};
```
@ -861,8 +908,13 @@ directive:
"SmbProperties": {"$ref": "#/definitions/FileSmbProperties", "x-ms-xml": {"name": ""}},
"LeaseDuration": {"$ref": "#/definitions/LeaseDuration"},
"LeaseState": {"$ref": "#/definitions/LeaseState"},
"LeaseStatus": {"$ref": "#/definitions/LeaseStatus"}
}
"LeaseStatus": {"$ref": "#/definitions/LeaseStatus"},
"FileMode": {"type": "string", "x-nullable": true},
"Owner": {"type": "string", "x-nullable": true},
"Group": {"type": "string", "x-nullable": true},
"LinkCount": {"type": "integer", "format": "int64", "x-nullable": true},
},
"x-namespace" : "_detail"
};
$.DownloadFileResult = {
"type": "object",
@ -874,7 +926,8 @@ directive:
"TransactionalContentHash": {"$ref": "#/definitions/ContentHash", "x-nullable": true, "x-ms-xml": {"name": ""}},
"HttpHeaders": {"$ref": "#/definitions/FileHttpHeaders", "x-ms-xml": {"name": ""}},
"Details": {"$ref": "#/definitions/DownloadFileDetails", "x-ms-xml": {"name": ""}}
}
},
"x-namespace" : "_detail"
};
- from: swagger-document
where: $["x-ms-paths"]["/{shareName}/{directory}/{fileName}"].get.responses
@ -905,11 +958,17 @@ directive:
$[status_code].headers["x-ms-server-encrypted"]["x-ms-client-path"] = "Details.IsServerEncrypted";
$[status_code].headers["x-ms-file-permission-key"]["x-ms-client-path"] = "Details.SmbProperties.PermissionKey";
$[status_code].headers["x-ms-file-attributes"]["x-ms-client-path"] = "Details.SmbProperties.Attributes";
$[status_code].headers["x-ms-file-attributes"]["x-nullable"] = true;
$[status_code].headers["x-ms-file-attributes"]["x-ms-client-default"] = "None";
$[status_code].headers["x-ms-file-creation-time"]["x-ms-client-path"] = "Details.SmbProperties.CreatedOn";
$[status_code].headers["x-ms-file-last-write-time"]["x-ms-client-path"] = "Details.SmbProperties.LastWrittenOn";
$[status_code].headers["x-ms-file-change-time"]["x-ms-client-path"] = "Details.SmbProperties.ChangedOn";
$[status_code].headers["x-ms-file-id"]["x-ms-client-path"] = "Details.SmbProperties.FileId";
$[status_code].headers["x-ms-file-parent-id"]["x-ms-client-path"] = "Details.SmbProperties.ParentFileId";
$[status_code].headers["x-ms-mode"]["x-ms-client-path"] = "Details.FileMode";
$[status_code].headers["x-ms-owner"]["x-ms-client-path"] = "Details.Owner";
$[status_code].headers["x-ms-group"]["x-ms-client-path"] = "Details.Group";
$[status_code].headers["x-ms-link-count"]["x-ms-client-path"] = "Details.LinkCount";
delete $[status_code].headers["Accept-Ranges"];
delete $[status_code].headers["Content-Length"];
delete $[status_code].headers["Content-Range"];
@ -928,6 +987,7 @@ directive:
- from: swagger-document
where: $["x-ms-paths"]["/{shareName}/{directory}/{fileName}"].delete.responses["202"]
transform: >
$.headers["x-ms-link-count"]["x-nullable"] = true;
$.schema = {
"type": "object",
"x-ms-client-name": "DeleteFileResult",
@ -1046,6 +1106,54 @@ directive:
$["x-ms-file-change-time"].format = "date-time";
```
### CreateFileSymbolicLink
```yaml
directive:
- from: swagger-document
where: $["x-ms-paths"]["/{shareName}/{directory}/{fileName}?restype=symboliclink"].put.responses["201"]
transform: >
$.headers["x-ms-file-creation-time"]["x-ms-client-path"] = "SmbProperties.CreatedOn";
$.headers["x-ms-file-last-write-time"]["x-ms-client-path"] = "SmbProperties.LastWrittenOn";
$.headers["x-ms-file-change-time"]["x-ms-client-path"] = "SmbProperties.ChangedOn";
$.headers["x-ms-file-id"]["x-ms-client-path"] = "SmbProperties.FileId";
$.headers["x-ms-file-parent-id"]["x-ms-client-path"] = "SmbProperties.ParentFileId";
$.schema = {
"type": "object",
"x-ms-client-name": "CreateFileSymbolicLinkResult",
"x-ms-sealed": false,
"properties": {
"Created": {"type": "boolean", "x-ms-client-default": true, "x-ms-xml": {"name": ""}},
"SmbProperties": {"$ref": "#/definitions/FileSmbProperties", "x-ms-xml": {"name": ""}}
},
"x-namespace" : "_detail"
};
```
### CreateFileHardLink
```yaml
directive:
- from: swagger-document
where: $["x-ms-paths"]["/{shareName}/{directory}/{fileName}?restype=hardlink"].put.responses["201"]
transform: >
$.headers["x-ms-file-creation-time"]["x-ms-client-path"] = "SmbProperties.CreatedOn";
$.headers["x-ms-file-last-write-time"]["x-ms-client-path"] = "SmbProperties.LastWrittenOn";
$.headers["x-ms-file-change-time"]["x-ms-client-path"] = "SmbProperties.ChangedOn";
$.headers["x-ms-file-id"]["x-ms-client-path"] = "SmbProperties.FileId";
$.headers["x-ms-file-parent-id"]["x-ms-client-path"] = "SmbProperties.ParentFileId";
$.schema = {
"type": "object",
"x-ms-client-name": "CreateFileHardLinkResult",
"x-ms-sealed": false,
"properties": {
"Created": {"type": "boolean", "x-ms-client-default": true, "x-ms-xml": {"name": ""}},
"SmbProperties": {"$ref": "#/definitions/FileSmbProperties", "x-ms-xml": {"name": ""}}
},
"x-namespace" : "_detail"
};
```
### Description
```yaml

View File

@ -27,6 +27,7 @@ add_executable (
share_sas_test.cpp
share_service_client_test.cpp
share_service_client_test.hpp
share_utility_test.cpp
simplified_header_test.cpp
# Include shared test source code
${CMAKE_CURRENT_SOURCE_DIR}/../../../azure-storage-common/test/ut/test_base.cpp

View File

@ -1377,4 +1377,75 @@ namespace Azure { namespace Storage { namespace Test {
EXPECT_EQ(binaryPermission, permission);
}
}
TEST_F(FileShareDirectoryClientTest, PremiumNfsProperties_PLAYBACKONLY_)
{
auto shareServiceClient = *m_premiumShareServiceClient;
auto shareName = LowercaseRandomString();
auto shareClient = GetPremiumShareClientForTest(shareName);
Files::Shares::CreateShareOptions shareOptions;
shareOptions.EnabledProtocols = Files::Shares::Models::ShareProtocols::Nfs;
EXPECT_NO_THROW(shareClient.Create(shareOptions));
auto directoryName = LowercaseRandomString();
auto directoryClient
= shareClient.GetRootDirectoryClient().GetSubdirectoryClient(directoryName);
std::string octalMode = "0777";
// Create a file
Files::Shares::CreateDirectoryOptions createOptions;
createOptions.PosixProperties.FileMode
= Files::Shares::Models::NfsFileMode::ParseOctalFileMode(octalMode);
createOptions.PosixProperties.Group = "123";
createOptions.PosixProperties.Owner = "456";
createOptions.PosixProperties.NfsFileType = Files::Shares::Models::NfsFileType::Regular;
Files::Shares::Models::CreateDirectoryResult createResult;
EXPECT_NO_THROW(createResult = directoryClient.Create(createOptions).Value);
EXPECT_TRUE(createResult.PosixProperties.FileMode.HasValue());
EXPECT_EQ(createResult.PosixProperties.FileMode.Value().ToOctalFileMode(), octalMode);
EXPECT_TRUE(createResult.PosixProperties.Group.HasValue());
EXPECT_EQ(
createResult.PosixProperties.Group.Value(), createOptions.PosixProperties.Group.Value());
EXPECT_TRUE(createResult.PosixProperties.FileMode.HasValue());
EXPECT_EQ(
createResult.PosixProperties.Owner.Value(), createOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(createResult.PosixProperties.NfsFileType.HasValue());
EXPECT_EQ(
createResult.PosixProperties.NfsFileType.Value(),
Files::Shares::Models::NfsFileType::Directory);
// Set Properties
Files::Shares::SetDirectoryPropertiesOptions setOptions;
setOptions.PosixProperties.FileMode
= Files::Shares::Models::NfsFileMode::ParseOctalFileMode("0707");
setOptions.PosixProperties.Group = "123";
setOptions.PosixProperties.Owner = "456";
Files::Shares::Models::SetDirectoryPropertiesResult setResult;
EXPECT_NO_THROW(
setResult
= directoryClient.SetProperties(Files::Shares::Models::FileSmbProperties(), setOptions)
.Value);
EXPECT_TRUE(setResult.PosixProperties.FileMode.HasValue());
EXPECT_EQ(setResult.PosixProperties.FileMode.Value().ToOctalFileMode(), "0707");
EXPECT_TRUE(setResult.PosixProperties.Group.HasValue());
EXPECT_EQ(setResult.PosixProperties.Group.Value(), setOptions.PosixProperties.Group.Value());
EXPECT_TRUE(setResult.PosixProperties.Owner.HasValue());
EXPECT_EQ(setResult.PosixProperties.Owner.Value(), setOptions.PosixProperties.Owner.Value());
// Get Properties
Files::Shares::Models::DirectoryProperties properties;
EXPECT_NO_THROW(properties = directoryClient.GetProperties().Value);
EXPECT_TRUE(properties.PosixProperties.FileMode.HasValue());
EXPECT_EQ(properties.PosixProperties.FileMode.Value().ToOctalFileMode(), "0707");
EXPECT_TRUE(properties.PosixProperties.Group.HasValue());
EXPECT_EQ(properties.PosixProperties.Group.Value(), setOptions.PosixProperties.Group.Value());
EXPECT_TRUE(properties.PosixProperties.Owner.HasValue());
EXPECT_EQ(properties.PosixProperties.Owner.Value(), setOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(properties.PosixProperties.NfsFileType.HasValue());
EXPECT_EQ(
properties.PosixProperties.NfsFileType.Value(),
Files::Shares::Models::NfsFileType::Directory);
}
}}} // namespace Azure::Storage::Test

View File

@ -817,6 +817,128 @@ namespace Azure { namespace Storage { namespace Test {
}
}
TEST_F(FileShareFileClientTest, CopyWithSmbPropertyFlags)
{
auto sddlPermission
= "O:S-1-5-21-2127521184-1604012920-1887927527-21560751G:S-1-5-21-2127521184-1604012920-"
"1887927527-513D:(A;;FA;;;SY)(A;;FA;;;BA)(A;;0x1200a9;;;S-1-5-21-397955417-626881126-"
"188441444-3053964)";
Files::Shares::CreateFileOptions createOptions;
createOptions.SmbProperties.Attributes = Files::Shares::Models::FileAttributes::System
| Files::Shares::Models::FileAttributes::NotContentIndexed;
auto fileClient = m_shareClient->GetRootDirectoryClient().GetFileClient(RandomString() + "1");
fileClient.Create(128, createOptions);
auto sourceProperties = fileClient.GetProperties().Value;
auto fileProperties = m_fileClient->GetProperties().Value;
// None scenario
{
Files::Shares::StartFileCopyOptions options;
options.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::None;
options.SmbProperties.Attributes = Files::Shares::Models::FileAttributes::ReadOnly;
options.SmbProperties.CreatedOn = fileProperties.SmbProperties.CreatedOn;
options.SmbProperties.ChangedOn = fileProperties.SmbProperties.ChangedOn;
options.SmbProperties.LastWrittenOn = fileProperties.SmbProperties.LastWrittenOn;
options.PermissionCopyMode = Files::Shares::Models::PermissionCopyMode::Override;
options.Permission = sddlPermission;
auto destFileClient
= m_shareClient->GetRootDirectoryClient().GetFileClient(RandomString() + "2");
auto copyOperation = destFileClient.StartCopy(fileClient.GetUrl(), options);
EXPECT_EQ(
copyOperation.GetRawResponse().GetStatusCode(),
Azure::Core::Http::HttpStatusCode::Accepted);
auto destProperties = copyOperation.PollUntilDone(std::chrono::milliseconds(1000)).Value;
EXPECT_EQ(destProperties.CopyStatus.Value(), Files::Shares::Models::CopyStatus::Success);
destProperties = destFileClient.GetProperties().Value;
EXPECT_EQ(
destProperties.SmbProperties.Attributes,
options.SmbProperties.Attributes | Files::Shares::Models::FileAttributes::Archive);
EXPECT_EQ(
destProperties.SmbProperties.CreatedOn.Value(), options.SmbProperties.CreatedOn.Value());
EXPECT_EQ(
destProperties.SmbProperties.ChangedOn.Value(), options.SmbProperties.ChangedOn.Value());
EXPECT_EQ(
destProperties.SmbProperties.LastWrittenOn.Value(),
options.SmbProperties.LastWrittenOn.Value());
auto destPermissionKey = destProperties.SmbProperties.PermissionKey.Value();
std::string destPermission = m_shareClient->GetPermission(destPermissionKey).Value;
EXPECT_EQ(destPermission, sddlPermission);
}
// Source scenario
{
Files::Shares::StartFileCopyOptions options;
options.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::All;
options.SmbProperties.Attributes = Files::Shares::Models::FileAttributes::ReadOnly;
options.SmbProperties.CreatedOn = fileProperties.SmbProperties.CreatedOn;
options.SmbProperties.ChangedOn = fileProperties.SmbProperties.ChangedOn;
options.SmbProperties.LastWrittenOn = fileProperties.SmbProperties.LastWrittenOn;
options.PermissionCopyMode = Files::Shares::Models::PermissionCopyMode::Override;
options.SmbProperties.PermissionKey = "";
auto destFileClient
= m_shareClient->GetRootDirectoryClient().GetFileClient(RandomString() + "2");
auto copyOperation = destFileClient.StartCopy(fileClient.GetUrl(), options);
EXPECT_EQ(
copyOperation.GetRawResponse().GetStatusCode(),
Azure::Core::Http::HttpStatusCode::Accepted);
auto destProperties = copyOperation.PollUntilDone(std::chrono::milliseconds(1000)).Value;
EXPECT_EQ(destProperties.CopyStatus.Value(), Files::Shares::Models::CopyStatus::Success);
destProperties = destFileClient.GetProperties().Value;
EXPECT_EQ(destProperties.SmbProperties.Attributes, sourceProperties.SmbProperties.Attributes);
EXPECT_EQ(
destProperties.SmbProperties.CreatedOn.Value(),
sourceProperties.SmbProperties.CreatedOn.Value());
EXPECT_EQ(
destProperties.SmbProperties.ChangedOn.Value(),
sourceProperties.SmbProperties.ChangedOn.Value());
EXPECT_EQ(
destProperties.SmbProperties.LastWrittenOn.Value(),
sourceProperties.SmbProperties.LastWrittenOn.Value());
EXPECT_EQ(
destProperties.SmbProperties.PermissionKey.Value(),
sourceProperties.SmbProperties.PermissionKey.Value());
}
// Part Source Scenario
{
Files::Shares::StartFileCopyOptions options;
options.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::FileAttributes
| Files::Shares::CopyableFileSmbPropertyFlags::Permission;
options.SmbProperties.Attributes = Files::Shares::Models::FileAttributes::ReadOnly;
options.SmbProperties.CreatedOn = fileProperties.SmbProperties.CreatedOn;
options.SmbProperties.ChangedOn = fileProperties.SmbProperties.ChangedOn;
options.SmbProperties.LastWrittenOn = fileProperties.SmbProperties.LastWrittenOn;
options.PermissionCopyMode = Files::Shares::Models::PermissionCopyMode::Override;
options.SmbProperties.PermissionKey = "";
auto destFileClient
= m_shareClient->GetRootDirectoryClient().GetFileClient(RandomString() + "2");
auto copyOperation = destFileClient.StartCopy(fileClient.GetUrl(), options);
EXPECT_EQ(
copyOperation.GetRawResponse().GetStatusCode(),
Azure::Core::Http::HttpStatusCode::Accepted);
auto destProperties = copyOperation.PollUntilDone(std::chrono::milliseconds(1000)).Value;
EXPECT_EQ(destProperties.CopyStatus.Value(), Files::Shares::Models::CopyStatus::Success);
destProperties = destFileClient.GetProperties().Value;
EXPECT_EQ(destProperties.SmbProperties.Attributes, sourceProperties.SmbProperties.Attributes);
EXPECT_EQ(
destProperties.SmbProperties.CreatedOn.Value(), options.SmbProperties.CreatedOn.Value());
EXPECT_EQ(
destProperties.SmbProperties.ChangedOn.Value(), options.SmbProperties.ChangedOn.Value());
EXPECT_EQ(
destProperties.SmbProperties.LastWrittenOn.Value(),
options.SmbProperties.LastWrittenOn.Value());
EXPECT_EQ(
destProperties.SmbProperties.PermissionKey.Value(),
sourceProperties.SmbProperties.PermissionKey.Value());
}
}
TEST_F(FileShareFileClientTest, RangeRelated)
{
size_t fileSize = 1024 * 3;
@ -2089,4 +2211,352 @@ namespace Azure { namespace Storage { namespace Test {
EXPECT_EQ(binaryPermission, permission);
}
}
TEST_F(FileShareFileClientTest, PremiumNfsProperties_PLAYBACKONLY_)
{
auto shareServiceClient = *m_premiumShareServiceClient;
auto shareName = LowercaseRandomString();
auto shareClient = GetPremiumShareClientForTest(shareName);
Files::Shares::CreateShareOptions shareOptions;
shareOptions.EnabledProtocols = Files::Shares::Models::ShareProtocols::Nfs;
EXPECT_NO_THROW(shareClient.Create(shareOptions));
auto otherProperties = m_fileClient->GetProperties().Value;
auto fileName = LowercaseRandomString();
auto fileClient = shareClient.GetRootDirectoryClient().GetFileClient(fileName);
std::string octalMode = "0777";
// Create a file
Files::Shares::CreateFileOptions createOptions;
createOptions.PosixProperties.FileMode
= Files::Shares::Models::NfsFileMode::ParseOctalFileMode(octalMode);
createOptions.PosixProperties.Group = "123";
createOptions.PosixProperties.Owner = "456";
createOptions.PosixProperties.NfsFileType = Files::Shares::Models::NfsFileType::Regular;
Files::Shares::Models::CreateFileResult createResult;
EXPECT_NO_THROW(createResult = fileClient.Create(256, createOptions).Value);
EXPECT_TRUE(createResult.PosixProperties.FileMode.HasValue());
EXPECT_EQ(createResult.PosixProperties.FileMode.Value().ToOctalFileMode(), octalMode);
EXPECT_TRUE(createResult.PosixProperties.Group.HasValue());
EXPECT_EQ(
createResult.PosixProperties.Group.Value(), createOptions.PosixProperties.Group.Value());
EXPECT_TRUE(createResult.PosixProperties.FileMode.HasValue());
EXPECT_EQ(
createResult.PosixProperties.Owner.Value(), createOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(createResult.PosixProperties.NfsFileType.HasValue());
EXPECT_EQ(
createResult.PosixProperties.NfsFileType.Value(),
Files::Shares::Models::NfsFileType::Regular);
// Set Properties
Files::Shares::SetFilePropertiesOptions setOptions;
setOptions.PosixProperties.FileMode
= Files::Shares::Models::NfsFileMode::ParseOctalFileMode("0707");
setOptions.PosixProperties.Group = "123";
setOptions.PosixProperties.Owner = "456";
Files::Shares::Models::SetFilePropertiesResult setResult;
EXPECT_NO_THROW(
setResult = fileClient
.SetProperties(
Files::Shares::Models::FileHttpHeaders(),
Files::Shares::Models::FileSmbProperties(),
setOptions)
.Value);
EXPECT_TRUE(setResult.PosixProperties.FileMode.HasValue());
EXPECT_EQ(setResult.PosixProperties.FileMode.Value().ToOctalFileMode(), "0707");
EXPECT_TRUE(setResult.PosixProperties.Group.HasValue());
EXPECT_EQ(setResult.PosixProperties.Group.Value(), setOptions.PosixProperties.Group.Value());
EXPECT_TRUE(setResult.PosixProperties.Owner.HasValue());
EXPECT_EQ(setResult.PosixProperties.Owner.Value(), setOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(setResult.PosixProperties.LinkCount.HasValue());
// Get Properties
Files::Shares::Models::FileProperties properties;
EXPECT_NO_THROW(properties = fileClient.GetProperties().Value);
EXPECT_TRUE(properties.PosixProperties.FileMode.HasValue());
EXPECT_EQ(properties.PosixProperties.FileMode.Value().ToOctalFileMode(), "0707");
EXPECT_TRUE(properties.PosixProperties.Group.HasValue());
EXPECT_EQ(properties.PosixProperties.Group.Value(), setOptions.PosixProperties.Group.Value());
EXPECT_TRUE(properties.PosixProperties.Owner.HasValue());
EXPECT_EQ(properties.PosixProperties.Owner.Value(), setOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(properties.PosixProperties.LinkCount.HasValue());
EXPECT_TRUE(properties.PosixProperties.NfsFileType.HasValue());
EXPECT_EQ(
properties.PosixProperties.NfsFileType.Value(),
Files::Shares::Models::NfsFileType::Regular);
// Download
Files::Shares::Models::DownloadFileResult downloadResult;
EXPECT_NO_THROW(downloadResult = fileClient.Download().Value);
EXPECT_TRUE(downloadResult.Details.PosixProperties.FileMode.HasValue());
EXPECT_EQ(downloadResult.Details.PosixProperties.FileMode.Value().ToOctalFileMode(), "0707");
EXPECT_TRUE(downloadResult.Details.PosixProperties.Group.HasValue());
EXPECT_EQ(
downloadResult.Details.PosixProperties.Group.Value(),
setOptions.PosixProperties.Group.Value());
EXPECT_TRUE(downloadResult.Details.PosixProperties.Owner.HasValue());
EXPECT_EQ(
downloadResult.Details.PosixProperties.Owner.Value(),
setOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(downloadResult.Details.PosixProperties.LinkCount.HasValue());
// DownloadTo
Files::Shares::Models::DownloadFileToResult downloadToResult;
std::string tempFilename = RandomString() + "1";
EXPECT_NO_THROW(downloadToResult = fileClient.DownloadTo(tempFilename).Value);
EXPECT_TRUE(downloadToResult.Details.PosixProperties.FileMode.HasValue());
EXPECT_EQ(downloadToResult.Details.PosixProperties.FileMode.Value().ToOctalFileMode(), "0707");
EXPECT_TRUE(downloadToResult.Details.PosixProperties.Group.HasValue());
EXPECT_EQ(
downloadToResult.Details.PosixProperties.Group.Value(),
setOptions.PosixProperties.Group.Value());
EXPECT_TRUE(downloadToResult.Details.PosixProperties.Owner.HasValue());
EXPECT_EQ(
downloadToResult.Details.PosixProperties.Owner.Value(),
setOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(downloadToResult.Details.PosixProperties.LinkCount.HasValue());
DeleteFile(tempFilename);
std::vector<uint8_t> buff(256);
EXPECT_NO_THROW(downloadToResult = fileClient.DownloadTo(buff.data(), 256).Value);
EXPECT_TRUE(downloadToResult.Details.PosixProperties.FileMode.HasValue());
EXPECT_EQ(downloadToResult.Details.PosixProperties.FileMode.Value().ToOctalFileMode(), "0707");
EXPECT_TRUE(downloadToResult.Details.PosixProperties.Group.HasValue());
EXPECT_EQ(
downloadToResult.Details.PosixProperties.Group.Value(),
setOptions.PosixProperties.Group.Value());
EXPECT_TRUE(downloadToResult.Details.PosixProperties.Owner.HasValue());
EXPECT_EQ(
downloadToResult.Details.PosixProperties.Owner.Value(),
setOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(downloadToResult.Details.PosixProperties.LinkCount.HasValue());
// Create HardLink
auto hardLinkClient
= shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
Files::Shares::CreateHardLinkOptions createHardLinkOptions;
Files::Shares::Models::CreateFileHardLinkResult createFileHardLinkResult;
EXPECT_NO_THROW(
createFileHardLinkResult
= hardLinkClient.CreateHardLink(fileName, createHardLinkOptions).Value);
EXPECT_TRUE(createFileHardLinkResult.PosixProperties.FileMode.HasValue());
EXPECT_EQ(createFileHardLinkResult.PosixProperties.FileMode.Value().ToOctalFileMode(), "0707");
EXPECT_TRUE(createFileHardLinkResult.PosixProperties.Group.HasValue());
EXPECT_EQ(
createFileHardLinkResult.PosixProperties.Group.Value(),
createOptions.PosixProperties.Group.Value());
EXPECT_TRUE(createFileHardLinkResult.PosixProperties.FileMode.HasValue());
EXPECT_EQ(
createFileHardLinkResult.PosixProperties.Owner.Value(),
createOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(createFileHardLinkResult.PosixProperties.NfsFileType.HasValue());
EXPECT_EQ(
createFileHardLinkResult.PosixProperties.NfsFileType.Value(),
Files::Shares::Models::NfsFileType::Regular);
EXPECT_TRUE(createFileHardLinkResult.SmbProperties.CreatedOn.HasValue());
EXPECT_TRUE(createFileHardLinkResult.SmbProperties.LastWrittenOn.HasValue());
EXPECT_TRUE(createFileHardLinkResult.SmbProperties.ChangedOn.HasValue());
EXPECT_TRUE(!createFileHardLinkResult.SmbProperties.FileId.empty());
EXPECT_TRUE(!createFileHardLinkResult.SmbProperties.ParentFileId.empty());
EXPECT_TRUE(createFileHardLinkResult.ETag.HasValue());
// Delete
Files::Shares::Models::DeleteFileResult deleteResult;
EXPECT_NO_THROW(deleteResult = fileClient.Delete().Value);
EXPECT_TRUE(deleteResult.LinkCount.HasValue());
// Upload
size_t fileSize = 512;
std::vector<uint8_t> content(RandomBuffer(fileSize));
auto memBodyStream = Core::IO::MemoryBodyStream(content);
tempFilename = "file" + RandomString();
WriteFile(tempFilename, content);
Files::Shares::UploadFileFromOptions uploadOptions;
uploadOptions.PosixProperties.FileMode
= Files::Shares::Models::NfsFileMode::ParseOctalFileMode(octalMode);
uploadOptions.PosixProperties.Group = "123";
uploadOptions.PosixProperties.Owner = "456";
uploadOptions.PosixProperties.NfsFileType = Files::Shares::Models::NfsFileType::Regular;
// From buffer
fileClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
EXPECT_NO_THROW(fileClient.UploadFrom(content.data(), fileSize, uploadOptions));
properties = fileClient.GetProperties().Value;
EXPECT_TRUE(properties.PosixProperties.FileMode.HasValue());
EXPECT_EQ(properties.PosixProperties.FileMode.Value().ToOctalFileMode(), octalMode);
EXPECT_TRUE(properties.PosixProperties.Group.HasValue());
EXPECT_EQ(
properties.PosixProperties.Group.Value(), uploadOptions.PosixProperties.Group.Value());
EXPECT_TRUE(properties.PosixProperties.Owner.HasValue());
EXPECT_EQ(
properties.PosixProperties.Owner.Value(), uploadOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(properties.PosixProperties.LinkCount.HasValue());
EXPECT_TRUE(properties.PosixProperties.NfsFileType.HasValue());
EXPECT_EQ(
properties.PosixProperties.NfsFileType.Value(),
Files::Shares::Models::NfsFileType::Regular);
// From file
fileClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
EXPECT_NO_THROW(fileClient.UploadFrom(tempFilename, uploadOptions));
properties = fileClient.GetProperties().Value;
EXPECT_TRUE(properties.PosixProperties.FileMode.HasValue());
EXPECT_EQ(properties.PosixProperties.FileMode.Value().ToOctalFileMode(), octalMode);
EXPECT_TRUE(properties.PosixProperties.Group.HasValue());
EXPECT_EQ(
properties.PosixProperties.Group.Value(), uploadOptions.PosixProperties.Group.Value());
EXPECT_TRUE(properties.PosixProperties.Owner.HasValue());
EXPECT_EQ(
properties.PosixProperties.Owner.Value(), uploadOptions.PosixProperties.Owner.Value());
EXPECT_TRUE(properties.PosixProperties.LinkCount.HasValue());
EXPECT_TRUE(properties.PosixProperties.NfsFileType.HasValue());
EXPECT_EQ(
properties.PosixProperties.NfsFileType.Value(),
Files::Shares::Models::NfsFileType::Regular);
}
TEST_F(FileShareFileClientTest, PremiumNfsPropertiesForCopy_PLAYBACKONLY_)
{
auto shareServiceClient = *m_premiumShareServiceClient;
auto shareName = LowercaseRandomString();
auto shareClient = GetPremiumShareClientForTest(shareName);
Files::Shares::CreateShareOptions shareOptions;
shareOptions.EnabledProtocols = Files::Shares::Models::ShareProtocols::Nfs;
EXPECT_NO_THROW(shareClient.Create(shareOptions));
auto sourceName = LowercaseRandomString();
auto sourceClient = shareClient.GetRootDirectoryClient().GetFileClient(sourceName);
std::string sourceMode = "0777";
// Create a file
Files::Shares::CreateFileOptions createOptions;
createOptions.PosixProperties.FileMode
= Files::Shares::Models::NfsFileMode::ParseOctalFileMode(sourceMode);
createOptions.PosixProperties.Group = "123";
createOptions.PosixProperties.Owner = "456";
createOptions.PosixProperties.NfsFileType = Files::Shares::Models::NfsFileType::Regular;
EXPECT_NO_THROW(sourceClient.Create(256, createOptions));
// Copy with override
auto destFileClient
= shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
Files::Shares::StartFileCopyOptions copyOptions;
copyOptions.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::None;
copyOptions.PosixProperties.FileMode
= Files::Shares::Models::NfsFileMode::ParseOctalFileMode("0757");
copyOptions.ModeCopyMode = Files::Shares::Models::ModeCopyMode::Override;
copyOptions.PosixProperties.Group = "888";
copyOptions.PosixProperties.Owner = "999";
copyOptions.OwnerCopyMode = Files::Shares::Models::OwnerCopyMode::Override;
auto copyOperation = destFileClient.StartCopy(sourceClient.GetUrl(), copyOptions);
EXPECT_EQ(
copyOperation.GetRawResponse().GetStatusCode(),
Azure::Core::Http::HttpStatusCode::Accepted);
auto properties = copyOperation.PollUntilDone(std::chrono::milliseconds(1000)).Value;
EXPECT_EQ(properties.CopyStatus.Value(), Files::Shares::Models::CopyStatus::Success);
EXPECT_TRUE(properties.PosixProperties.FileMode.HasValue());
EXPECT_EQ(properties.PosixProperties.FileMode.Value().ToOctalFileMode(), "0757");
EXPECT_TRUE(properties.PosixProperties.Group.HasValue());
EXPECT_EQ(properties.PosixProperties.Group.Value(), copyOptions.PosixProperties.Group.Value());
EXPECT_TRUE(properties.PosixProperties.Owner.HasValue());
EXPECT_EQ(properties.PosixProperties.Owner.Value(), copyOptions.PosixProperties.Owner.Value());
// Copy with source
copyOptions = Files::Shares::StartFileCopyOptions();
copyOptions.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::None;
copyOptions.ModeCopyMode = Files::Shares::Models::ModeCopyMode::Source;
copyOptions.OwnerCopyMode = Files::Shares::Models::OwnerCopyMode::Source;
destFileClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
copyOperation = destFileClient.StartCopy(sourceClient.GetUrl(), copyOptions);
EXPECT_EQ(
copyOperation.GetRawResponse().GetStatusCode(),
Azure::Core::Http::HttpStatusCode::Accepted);
properties = copyOperation.PollUntilDone(std::chrono::milliseconds(1000)).Value;
EXPECT_EQ(properties.CopyStatus.Value(), Files::Shares::Models::CopyStatus::Success);
EXPECT_TRUE(properties.PosixProperties.FileMode.HasValue());
EXPECT_EQ(properties.PosixProperties.FileMode.Value().ToOctalFileMode(), sourceMode);
EXPECT_TRUE(properties.PosixProperties.Group.HasValue());
EXPECT_EQ(
properties.PosixProperties.Group.Value(), createOptions.PosixProperties.Group.Value());
EXPECT_TRUE(properties.PosixProperties.Owner.HasValue());
EXPECT_EQ(
properties.PosixProperties.Owner.Value(), createOptions.PosixProperties.Owner.Value());
// Copy with source/override
copyOptions = Files::Shares::StartFileCopyOptions();
copyOptions.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::None;
copyOptions.ModeCopyMode = Files::Shares::Models::ModeCopyMode::Override;
copyOptions.PosixProperties.FileMode
= Files::Shares::Models::NfsFileMode::ParseOctalFileMode("0767");
copyOptions.OwnerCopyMode = Files::Shares::Models::OwnerCopyMode::Source;
destFileClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
copyOperation = destFileClient.StartCopy(sourceClient.GetUrl(), copyOptions);
EXPECT_EQ(
copyOperation.GetRawResponse().GetStatusCode(),
Azure::Core::Http::HttpStatusCode::Accepted);
properties = copyOperation.PollUntilDone(std::chrono::milliseconds(1000)).Value;
EXPECT_EQ(properties.CopyStatus.Value(), Files::Shares::Models::CopyStatus::Success);
EXPECT_TRUE(properties.PosixProperties.FileMode.HasValue());
EXPECT_EQ(properties.PosixProperties.FileMode.Value().ToOctalFileMode(), "0767");
EXPECT_TRUE(properties.PosixProperties.Group.HasValue());
EXPECT_EQ(
properties.PosixProperties.Group.Value(), createOptions.PosixProperties.Group.Value());
EXPECT_TRUE(properties.PosixProperties.Owner.HasValue());
EXPECT_EQ(
properties.PosixProperties.Owner.Value(), createOptions.PosixProperties.Owner.Value());
// Copy without NfsProperties
copyOptions = Files::Shares::StartFileCopyOptions();
copyOptions.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::None;
destFileClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
copyOperation = destFileClient.StartCopy(sourceClient.GetUrl(), copyOptions);
EXPECT_EQ(
copyOperation.GetRawResponse().GetStatusCode(),
Azure::Core::Http::HttpStatusCode::Accepted);
properties = copyOperation.PollUntilDone(std::chrono::milliseconds(1000)).Value;
EXPECT_EQ(properties.CopyStatus.Value(), Files::Shares::Models::CopyStatus::Success);
EXPECT_TRUE(properties.PosixProperties.FileMode.HasValue());
EXPECT_EQ(properties.PosixProperties.FileMode.Value().ToOctalFileMode(), "0664");
EXPECT_TRUE(properties.PosixProperties.Group.HasValue());
EXPECT_EQ(properties.PosixProperties.Group.Value(), "0");
EXPECT_TRUE(properties.PosixProperties.Owner.HasValue());
EXPECT_EQ(properties.PosixProperties.Owner.Value(), "0");
// Copy with invalid input
copyOptions = Files::Shares::StartFileCopyOptions();
copyOptions.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::None;
copyOptions.ModeCopyMode = Files::Shares::Models::ModeCopyMode::Source;
copyOptions.PosixProperties.FileMode
= Files::Shares::Models::NfsFileMode::ParseOctalFileMode("0767");
copyOptions.OwnerCopyMode = Files::Shares::Models::OwnerCopyMode::Source;
destFileClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
EXPECT_THROW(destFileClient.StartCopy(sourceClient.GetUrl(), copyOptions), StorageException);
copyOptions = Files::Shares::StartFileCopyOptions();
copyOptions.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::None;
copyOptions.ModeCopyMode = Files::Shares::Models::ModeCopyMode::Override;
copyOptions.OwnerCopyMode = Files::Shares::Models::OwnerCopyMode::Source;
destFileClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
EXPECT_THROW(destFileClient.StartCopy(sourceClient.GetUrl(), copyOptions), StorageException);
copyOptions = Files::Shares::StartFileCopyOptions();
copyOptions.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::None;
copyOptions.ModeCopyMode = Files::Shares::Models::ModeCopyMode::Source;
copyOptions.OwnerCopyMode = Files::Shares::Models::OwnerCopyMode::Override;
destFileClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
EXPECT_THROW(destFileClient.StartCopy(sourceClient.GetUrl(), copyOptions), StorageException);
copyOptions = Files::Shares::StartFileCopyOptions();
copyOptions.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::None;
copyOptions.ModeCopyMode = Files::Shares::Models::ModeCopyMode::Source;
copyOptions.OwnerCopyMode = Files::Shares::Models::OwnerCopyMode::Source;
copyOptions.PosixProperties.Group = "888";
destFileClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString());
EXPECT_THROW(destFileClient.StartCopy(sourceClient.GetUrl(), copyOptions), StorageException);
}
}}} // namespace Azure::Storage::Test

View File

@ -0,0 +1,161 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include <azure/storage/files/shares.hpp>
#include <gtest/gtest.h>
/* cSpell:ignore rwsrwsrwt, rwxrwxrwx, rwSrwSrwT, xrwt, rwSr*/
namespace Azure { namespace Storage { namespace Test {
TEST(ShareUtilityTest, NfsFileMode)
{
auto testOctal = [&](const std::string& modeString) {
auto mode = Files::Shares::Models::NfsFileMode::ParseOctalFileMode(modeString);
EXPECT_EQ(mode.ToOctalFileMode(), modeString);
};
auto testSymbolic = [&](const std::string& modeString) {
auto mode = Files::Shares::Models::NfsFileMode::ParseSymbolicFileMode(modeString);
EXPECT_EQ(mode.ToSymbolicFileMode(), modeString);
};
auto testOctalToSymbolic = [&](const std::string& octal, const std::string& symbolic) {
auto mode = Files::Shares::Models::NfsFileMode::ParseOctalFileMode(octal);
EXPECT_EQ(mode.ToSymbolicFileMode(), symbolic);
};
auto testSymbolicToOctal = [&](const std::string& symbolic, const std::string& octal) {
auto mode = Files::Shares::Models::NfsFileMode::ParseSymbolicFileMode(symbolic);
EXPECT_EQ(mode.ToOctalFileMode(), octal);
};
// 0000
testOctal("0000");
testSymbolic("---------");
testOctalToSymbolic("0000", "---------");
testSymbolicToOctal("---------", "0000");
// 1111
testOctal("1111");
testSymbolic("--x--x--x");
testOctalToSymbolic("1111", "--x--x--t");
testSymbolicToOctal("--x--x--t", "1111");
// 2222
testOctal("2222");
testSymbolic("-w--wS-w-");
testOctalToSymbolic("2222", "-w--wS-w-");
testSymbolicToOctal("-w--wS-w-", "2222");
// 3333
testOctal("3333");
testSymbolic("-wx-ws-wt");
testOctalToSymbolic("3333", "-wx-ws-wt");
testSymbolicToOctal("-wx-ws-wt", "3333");
// 4444
testOctal("4444");
testSymbolic("r-Sr--r--");
testOctalToSymbolic("4444", "r-Sr--r--");
testSymbolicToOctal("r-Sr--r--", "4444");
// 5555
testOctal("5555");
testSymbolic("r-sr-xr-t");
testOctalToSymbolic("5555", "r-sr-xr-t");
testSymbolicToOctal("r-sr-xr-t", "5555");
// 6666
testOctal("6666");
testSymbolic("rwSrwSrw-");
testOctalToSymbolic("6666", "rwSrwSrw-");
testSymbolicToOctal("rwSrwSrw-", "6666");
// 7777
testOctal("7777");
testSymbolic("rwsrwsrwt");
testOctalToSymbolic("7777", "rwsrwsrwt");
testSymbolicToOctal("rwsrwsrwt", "7777");
// 0001
testOctal("0001");
testSymbolic("--------x");
testOctalToSymbolic("0001", "--------x");
testSymbolicToOctal("--------x", "0001");
// 0010
testOctal("0010");
testSymbolic("-----x---");
testOctalToSymbolic("0010", "-----x---");
testSymbolicToOctal("-----x---", "0010");
// 0100
testOctal("0100");
testSymbolic("--x------");
testOctalToSymbolic("0100", "--x------");
testSymbolicToOctal("--x------", "0100");
// 0124
testOctal("0124");
testSymbolic("--x-w-r--");
testOctalToSymbolic("0124", "--x-w-r--");
testSymbolicToOctal("--x-w-r--", "0124");
// 0777
testOctal("0777");
testSymbolic("rwxrwxrwx");
testOctalToSymbolic("0777", "rwxrwxrwx");
testSymbolicToOctal("rwxrwxrwx", "0777");
// 4210
testOctal("4210");
testSymbolic("-wS--x---");
testOctalToSymbolic("4210", "-wS--x---");
testSymbolicToOctal("-wS--x---", "4210");
// 1357
testOctal("1357");
testSymbolic("-wxr-xrwt");
testOctalToSymbolic("1357", "-wxr-xrwt");
testSymbolicToOctal("-wxr-xrwt", "1357");
// 7654
testOctal("7654");
testSymbolic("rwSr-sr-T");
testOctalToSymbolic("7654", "rwSr-sr-T");
testSymbolicToOctal("rwSr-sr-T", "7654");
// 7666
testOctal("7666");
testSymbolic("rwSrwSrwT");
testOctalToSymbolic("7666", "rwSrwSrwT");
testSymbolicToOctal("rwSrwSrwT", "7666");
// Invalid
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseOctalFileMode("1239"), std::invalid_argument);
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseOctalFileMode("9786"), std::invalid_argument);
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseOctalFileMode("12344"), std::invalid_argument);
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseOctalFileMode("12"), std::invalid_argument);
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseOctalFileMode("test"), std::invalid_argument);
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseOctalFileMode("rwSrwSrwT"), std::invalid_argument);
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseSymbolicFileMode("1234"), std::invalid_argument);
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseSymbolicFileMode("raSrwSrwT"),
std::invalid_argument);
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseSymbolicFileMode("---rwxrwxrwx"),
std::invalid_argument);
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseSymbolicFileMode("---rwx"), std::invalid_argument);
EXPECT_THROW(
Files::Shares::Models::NfsFileMode::ParseSymbolicFileMode("---test"),
std::invalid_argument);
}
}}} // namespace Azure::Storage::Test