Skip to content

Commit 3d222a3

Browse files
linuxsmithsmicrosoft-github-policy-service[bot]Nagendra Tomar
authored
Enable support for preserving SMB info on Linux. (#1723)
* Microsoft mandatory file * Enable support for preserving SMB info on Linux. Implemented the GetSDDL/PutSDDL GetSMBProperties/PutSMBProperties methods for Linux using extended attributes. Following are the xattrs we use for fetching/setting various required info. // Extended Attribute (xattr) keys for fetching various information from Linux cifs client. const ( CIFS_XATTR_CREATETIME = "user.cifs.creationtime" // File creation time. CIFS_XATTR_ATTRIB = "user.cifs.dosattrib" // FileAttributes. CIFS_XATTR_CIFS_ACL = "system.cifs_acl" // DACL only. CIFS_XATTR_CIFS_NTSD = "system.cifs_ntsd" // Owner, Group, DACL. CIFS_XATTR_CIFS_NTSD_FULL = "system.cifs_ntsd_full" // Owner, Group, DACL, SACL. ) Majority of the changes are in sddl/sddlHelper_linux.go which implement the following Win32 APIs for dealing with SIDs. ConvertSecurityDescriptorToStringSecurityDescriptorW ConvertStringSecurityDescriptorToSecurityDescriptorW ConvertSidToStringSidW ConvertStringSidToSidW Note: I have skipped Object ACE support in sddl/sddlHelper_linux.go as those should not be used for filesystem properties, only AD object properties. Can someone confirm this? TBD: Conditional SID * Audited, fixed, tested support for "No ACL"/NO_ACCESS_CONTROL and ACL w/o any ACE Tested the following cases: c:\Users\natomar\Downloads>cd testacl // This has "No ACLs" and everyone should be allowed access. c:\Users\natomar\Downloads\testacl>touch NO_ACCESS_CONTROL.txt c:\Users\natomar\Downloads\testacl>cacls NO_ACCESS_CONTROL.txt /S:D:NO_ACCESS_CONTROL Are you sure (Y/N)?y processed file: c:\Users\natomar\Downloads\testacl\NO_ACCESS_CONTROL.txt // This has "No ACLs" and everyone should be allowed access. // It additionally has the "P" (protected) flag set, but that won't have // any effect as that just prevents ACE inheritance but this ACL will // not have any ACLs due to the NO_ACCESS_CONTROL flag. c:\Users\natomar\Downloads\testacl>touch PNO_ACCESS_CONTROL.txt c:\Users\natomar\Downloads\testacl>cacls PNO_ACCESS_CONTROL.txt /S:D:PNO_ACCESS_CONTROL Are you sure (Y/N)?y processed file: c:\Users\natomar\Downloads\testacl\PNO_ACCESS_CONTROL.txt // This should set DACL but with no ACEs, but since "P" is not set it // inherits ACEs from the parent dir. c:\Users\natomar\Downloads\testacl>touch empty_d.txt c:\Users\natomar\Downloads\testacl>cacls empty_d.txt /S:D: Are you sure (Y/N)?y processed file: c:\Users\natomar\Downloads\testacl\empty_d.txt // This should set DACL but with no ACEs, but since "P" is set it // doesn't inherit ACEs from the parent dir and hence this will block // all users. c:\Users\natomar\Downloads\testacl>touch empty_d_with_p.txt c:\Users\natomar\Downloads\testacl>cacls empty_d_with_p.txt /S:D:P Are you sure (Y/N)?y processed file: c:\Users\natomar\Downloads\testacl\empty_d_with_p.txt * Don't fail outright for ACL revision 4. Though our supported ACL types must carry ACL revision 2 as per the doc https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/20233ed8-a6c6-4097-aafa-dd545ed24428 but I've seen some dirs have ACL revision 4 but ACL types are still supported ones. So instead of failing upfront, let it fail with unsupported ACE type. Also hexadecimal aceRights are more commonly seen than I expected, so removing a log. * Minor fix after running azcopy on a large dir. This was something which I have doubt on. Now that we got a real world issue due to this, it's all clear :-) * Some minor updates after the rebase to latest Azcopy. * Set default value of flag preserve-smb-info to true on Windows and false on other OS (cherry picked from commit ac5bedb) Co-authored-by: microsoft-github-policy-service[bot] <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com> Co-authored-by: Nagendra Tomar <Nagendra.Tomar@microsoft.com>
1 parent 4557448 commit 3d222a3

10 files changed

+2196
-28
lines changed

cmd/copy.go

+9-11
Original file line numberDiff line numberDiff line change
@@ -649,11 +649,7 @@ func (raw rawCopyCmdArgs) cook() (CookedCopyCmdArgs, error) {
649649
glcm.SetOutputFormat(common.EOutputFormat.None())
650650
}
651651

652-
cooked.preserveSMBInfo = areBothLocationsSMBAware(cooked.FromTo)
653-
// If user has explicitly specified not to copy SMB Information, set cooked.preserveSMBInfo to false
654-
if !raw.preserveSMBInfo {
655-
cooked.preserveSMBInfo = false
656-
}
652+
cooked.preserveSMBInfo = raw.preserveSMBInfo && areBothLocationsSMBAware(cooked.FromTo)
657653

658654
cooked.preservePOSIXProperties = raw.preservePOSIXProperties
659655
if cooked.preservePOSIXProperties && !areBothLocationsPOSIXAware(cooked.FromTo) {
@@ -928,10 +924,11 @@ func validateForceIfReadOnly(toForce bool, fromTo common.FromTo) error {
928924

929925
func areBothLocationsSMBAware(fromTo common.FromTo) bool {
930926
// preserverSMBInfo will be true by default for SMB-aware locations unless specified false.
931-
// 1. Upload (Windows -> Azure File)
932-
// 2. Download (Azure File -> Windows)
927+
// 1. Upload (Windows/Linux -> Azure File)
928+
// 2. Download (Azure File -> Windows/Linux)
933929
// 3. S2S (Azure File -> Azure File)
934-
if runtime.GOOS == "windows" && (fromTo == common.EFromTo.LocalFile() || fromTo == common.EFromTo.FileLocal()) {
930+
if (runtime.GOOS == "windows" || runtime.GOOS == "linux") &&
931+
(fromTo == common.EFromTo.LocalFile() || fromTo == common.EFromTo.FileLocal()) {
935932
return true
936933
} else if fromTo == common.EFromTo.FileFile() {
937934
return true
@@ -956,8 +953,9 @@ func validatePreserveSMBPropertyOption(toPreserve bool, fromTo common.FromTo, ov
956953
return fmt.Errorf("%s is set but the job is not between %s-aware resources", flagName, common.IffString(flagName == PreservePermissionsFlag, "permission", "SMB"))
957954
}
958955

959-
if toPreserve && (fromTo.IsUpload() || fromTo.IsDownload()) && runtime.GOOS != "windows" {
960-
return fmt.Errorf("%s is set but persistence for up/downloads is a Windows-only feature", flagName)
956+
if toPreserve && (fromTo.IsUpload() || fromTo.IsDownload()) &&
957+
runtime.GOOS != "windows" && runtime.GOOS != "linux" {
958+
return fmt.Errorf("%s is set but persistence for up/downloads is supported only in Windows and Linux", flagName)
961959
}
962960

963961
return nil
@@ -1946,7 +1944,7 @@ func init() {
19461944
cpCmd.PersistentFlags().BoolVar(&raw.preserveSMBPermissions, "preserve-smb-permissions", false, "False by default. Preserves SMB ACLs between aware resources (Windows and Azure Files). For downloads, you will also need the --backup flag to restore permissions where the new Owner will not be the user running AzCopy. This flag applies to both files and folders, unless a file-only filter is specified (e.g. include-pattern).")
19471945
cpCmd.PersistentFlags().BoolVar(&raw.asSubdir, "as-subdir", true, "True by default. Places folder sources as subdirectories under the destination.")
19481946
cpCmd.PersistentFlags().BoolVar(&raw.preserveOwner, common.PreserveOwnerFlagName, common.PreserveOwnerDefault, "Only has an effect in downloads, and only when --preserve-smb-permissions is used. If true (the default), the file Owner and Group are preserved in downloads. If set to false, --preserve-smb-permissions will still preserve ACLs but Owner and Group will be based on the user running AzCopy")
1949-
cpCmd.PersistentFlags().BoolVar(&raw.preserveSMBInfo, "preserve-smb-info", true, "For SMB-aware locations, flag will be set to true by default. Preserves SMB property info (last write time, creation time, attribute bits) between SMB-aware resources (Windows and Azure Files). Only the attribute bits supported by Azure Files will be transferred; any others will be ignored. This flag applies to both files and folders, unless a file-only filter is specified (e.g. include-pattern). The info transferred for folders is the same as that for files, except for Last Write Time which is never preserved for folders.")
1947+
cpCmd.PersistentFlags().BoolVar(&raw.preserveSMBInfo, "preserve-smb-info", (runtime.GOOS == "windows"), "Preserves SMB property info (last write time, creation time, attribute bits) between SMB-aware resources (Windows and Azure Files). On windows, this flag will be set to true by default. If the source or destination is a volume mounted on Linux using SMB protocol, this flag will have to be explicitly set to true. Only the attribute bits supported by Azure Files will be transferred; any others will be ignored. This flag applies to both files and folders, unless a file-only filter is specified (e.g. include-pattern). The info transferred for folders is the same as that for files, except for Last Write Time which is never preserved for folders.")
19501948
cpCmd.PersistentFlags().BoolVar(&raw.preservePOSIXProperties, "preserve-posix-properties", false, "'Preserves' property info gleaned from stat or statx into object metadata.")
19511949
cpCmd.PersistentFlags().BoolVar(&raw.forceIfReadOnly, "force-if-read-only", false, "When overwriting an existing file on Windows or Azure Files, force the overwrite to work even if the existing file has its read-only attribute set")
19521950
cpCmd.PersistentFlags().BoolVar(&raw.backupMode, common.BackupModeFlagName, false, "Activates Windows' SeBackupPrivilege for uploads, or SeRestorePrivilege for downloads, to allow AzCopy to see read all files, regardless of their file system permissions, and to restore all permissions. Requires that the account running AzCopy already has these permissions (e.g. has Administrator rights or is a member of the 'Backup Operators' group). All this flag does is activate privileges that the account already has")

cmd/sync.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ import (
2424
"context"
2525
"encoding/json"
2626
"fmt"
27-
"github.com/Azure/azure-storage-azcopy/v10/jobsAdmin"
27+
"runtime"
2828
"strings"
2929
"sync/atomic"
3030
"time"
3131

32+
"github.com/Azure/azure-storage-azcopy/v10/jobsAdmin"
33+
3234
"github.com/Azure/azure-pipeline-go/pipeline"
3335

3436
"github.com/Azure/azure-storage-azcopy/v10/common"
@@ -239,11 +241,7 @@ func (raw *rawSyncCmdArgs) cook() (cookedSyncCmdArgs, error) {
239241
cooked.includeFileAttributes = raw.parsePatterns(raw.includeFileAttributes)
240242
cooked.excludeFileAttributes = raw.parsePatterns(raw.excludeFileAttributes)
241243

242-
cooked.preserveSMBInfo = areBothLocationsSMBAware(cooked.fromTo)
243-
// If user has explicitly specified not to copy SMB Information, set cooked.preserveSMBInfo to false
244-
if !raw.preserveSMBInfo {
245-
cooked.preserveSMBInfo = false
246-
}
244+
cooked.preserveSMBInfo = raw.preserveSMBInfo && areBothLocationsSMBAware(cooked.fromTo)
247245

248246
if err = validatePreserveSMBPropertyOption(cooked.preserveSMBInfo, cooked.fromTo, nil, "preserve-smb-info"); err != nil {
249247
return cooked, err
@@ -751,7 +749,11 @@ func init() {
751749
// TODO: enable for copy with IfSourceNewer
752750
// smb info/permissions can be persisted in the scenario of File -> File
753751
syncCmd.PersistentFlags().BoolVar(&raw.preserveSMBPermissions, "preserve-smb-permissions", false, "False by default. Preserves SMB ACLs between aware resources (Azure Files). This flag applies to both files and folders, unless a file-only filter is specified (e.g. include-pattern).")
754-
syncCmd.PersistentFlags().BoolVar(&raw.preserveSMBInfo, "preserve-smb-info", true, "For SMB-aware locations, flag will be set to true by default. Preserves SMB property info (last write time, creation time, attribute bits) between SMB-aware resources (Azure Files). This flag applies to both files and folders, unless a file-only filter is specified (e.g. include-pattern). The info transferred for folders is the same as that for files, except for Last Write Time which is not preserved for folders. ")
752+
syncCmd.PersistentFlags().BoolVar(&raw.preserveSMBInfo, "preserve-smb-info", (runtime.GOOS=="windows"), "Preserves SMB property info (last write time, creation time, attribute bits)"+
753+
" between SMB-aware resources (Windows and Azure Files). On windows, this flag will be set to true by default. If the source or destination is a "+
754+
"volume mounted on Linux using SMB protocol, this flag will have to be explicitly set to true. Only the attribute bits supported by Azure Files "+
755+
"will be transferred; any others will be ignored. This flag applies to both files and folders, unless a file-only filter is specified "+
756+
"(e.g. include-pattern). The info transferred for folders is the same as that for files, except for Last Write Time which is never preserved for folders.")
755757
syncCmd.PersistentFlags().BoolVar(&raw.preservePOSIXProperties, "preserve-posix-properties", false, "'Preserves' property info gleaned from stat or statx into object metadata.")
756758

757759
// TODO: enable when we support local <-> File

common/writeThoughFile_linux.go

+133
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,143 @@
2121
package common
2222

2323
import (
24+
"encoding/binary"
25+
"fmt"
2426
"os"
2527
"syscall"
28+
"time"
29+
30+
"github.com/pkg/xattr"
31+
"golang.org/x/sys/unix"
32+
)
33+
34+
// Extended Attribute (xattr) keys for fetching various information from Linux cifs client.
35+
const (
36+
CIFS_XATTR_CREATETIME = "user.cifs.creationtime" // File creation time.
37+
CIFS_XATTR_ATTRIB = "user.cifs.dosattrib" // FileAttributes.
38+
CIFS_XATTR_CIFS_ACL = "system.cifs_acl" // DACL only.
39+
CIFS_XATTR_CIFS_NTSD = "system.cifs_ntsd" // Owner, Group, DACL.
40+
CIFS_XATTR_CIFS_NTSD_FULL = "system.cifs_ntsd_full" // Owner, Group, DACL, SACL.
2641
)
2742

43+
// 100-nanosecond intervals from Windows Epoch (January 1, 1601) to Unix Epoch (January 1, 1970).
44+
const (
45+
TICKS_FROM_WINDOWS_EPOCH_TO_UNIX_EPOCH = 116444736000000000
46+
)
47+
48+
// windows.Filetime.
49+
type Filetime struct {
50+
LowDateTime uint32
51+
HighDateTime uint32
52+
}
53+
54+
// windows.ByHandleFileInformation
55+
type ByHandleFileInformation struct {
56+
FileAttributes uint32
57+
CreationTime Filetime
58+
LastAccessTime Filetime
59+
LastWriteTime Filetime
60+
VolumeSerialNumber uint32
61+
FileSizeHigh uint32
62+
FileSizeLow uint32
63+
NumberOfLinks uint32
64+
FileIndexHigh uint32
65+
FileIndexLow uint32
66+
}
67+
68+
// Nanoseconds converts Filetime (as ticks since Windows Epoch) to nanoseconds since Unix Epoch (January 1, 1970).
69+
func (ft *Filetime) Nanoseconds() int64 {
70+
// 100-nanosecond intervals (ticks) since Windows Epoch (January 1, 1601).
71+
nsec := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime)
72+
73+
// 100-nanosecond intervals since Unix Epoch (January 1, 1970).
74+
nsec -= TICKS_FROM_WINDOWS_EPOCH_TO_UNIX_EPOCH
75+
76+
// nanoseconds since Unix Epoch.
77+
return nsec * 100
78+
}
79+
80+
// Convert nanoseconds since Unix Epoch (January 1, 1970) to Filetime since Windows Epoch (January 1, 1601).
81+
func NsecToFiletime(nsec int64) Filetime {
82+
// 100-nanosecond intervals since Unix Epoch (January 1, 1970).
83+
nsec /= 100
84+
85+
// 100-nanosecond intervals since Windows Epoch (January 1, 1601).
86+
nsec += TICKS_FROM_WINDOWS_EPOCH_TO_UNIX_EPOCH
87+
88+
return Filetime{LowDateTime: uint32(nsec & 0xFFFFFFFF), HighDateTime: uint32(nsec >> 32)}
89+
}
90+
91+
// WindowsTicksToUnixNano converts ticks (100-ns intervals) since Windows Epoch to nanoseconds since Unix Epoch.
92+
func WindowsTicksToUnixNano(ticks int64) int64 {
93+
// 100-nanosecond intervals since Unix Epoch (January 1, 1970).
94+
ticks -= TICKS_FROM_WINDOWS_EPOCH_TO_UNIX_EPOCH
95+
96+
// nanoseconds since Unix Epoch (January 1, 1970).
97+
return ticks * 100
98+
}
99+
100+
// UnixNanoToWindowsTicks converts nanoseconds since Unix Epoch to ticks since Windows Epoch.
101+
func UnixNanoToWindowsTicks(nsec int64) int64 {
102+
// 100-nanosecond intervals since Unix Epoch (January 1, 1970).
103+
nsec /= 100
104+
105+
// 100-nanosecond intervals since Windows Epoch (January 1, 1601).
106+
nsec += TICKS_FROM_WINDOWS_EPOCH_TO_UNIX_EPOCH
107+
108+
return nsec
109+
}
110+
111+
// StatxTimestampToFiletime converts the unix StatxTimestamp (sec, nsec) to the Windows' Filetime.
112+
// Note that StatxTimestamp is from Unix Epoch while Filetime holds time from Windows Epoch.
113+
func StatxTimestampToFiletime(ts unix.StatxTimestamp) Filetime {
114+
return NsecToFiletime(ts.Sec*int64(time.Second) + int64(ts.Nsec))
115+
}
116+
117+
func GetFileInformation(path string) (ByHandleFileInformation, error) {
118+
var stx unix.Statx_t
119+
120+
// We want all attributes including Btime (aka creation time).
121+
// For consistency with Windows implementation we pass flags==0 which causes it to follow symlinks.
122+
err := unix.Statx(unix.AT_FDCWD, path, 0 /* flags */, unix.STATX_ALL, &stx)
123+
if err == unix.ENOSYS || err == unix.EPERM {
124+
panic(fmt.Errorf("statx syscall is not available: %v", err))
125+
} else if err != nil {
126+
return ByHandleFileInformation{}, fmt.Errorf("statx(%s) failed: %v", path, err)
127+
}
128+
129+
// For getting FileAttributes we need to query the CIFS_XATTR_ATTRIB extended attribute.
130+
// Note: This doesn't necessarily cause a new QUERY_PATH_INFO call to the SMB server, instead
131+
// the value cached in the inode (likely as a result of the above Statx call) will be
132+
// returned.
133+
xattrbuf, err := xattr.Get(path, CIFS_XATTR_ATTRIB)
134+
if err != nil {
135+
return ByHandleFileInformation{},
136+
fmt.Errorf("xattr.Get(%s, %s) failed: %v", path, CIFS_XATTR_ATTRIB, err)
137+
}
138+
139+
var info ByHandleFileInformation
140+
141+
info.FileAttributes = binary.LittleEndian.Uint32(xattrbuf)
142+
143+
info.CreationTime = StatxTimestampToFiletime(stx.Btime)
144+
info.LastAccessTime = StatxTimestampToFiletime(stx.Atime)
145+
info.LastWriteTime = StatxTimestampToFiletime(stx.Mtime)
146+
147+
// TODO: Do we need this?
148+
info.VolumeSerialNumber = 0
149+
150+
info.FileSizeHigh = uint32(stx.Size >> 32)
151+
info.FileSizeLow = uint32(stx.Size & 0xFFFFFFFF)
152+
153+
info.NumberOfLinks = stx.Nlink
154+
155+
info.FileIndexHigh = uint32(stx.Ino >> 32)
156+
info.FileIndexLow = uint32(stx.Ino & 0xFFFFFFFF)
157+
158+
return info, nil
159+
}
160+
28161
func CreateFileOfSizeWithWriteThroughOption(destinationPath string, fileSize int64, writeThrough bool, t FolderCreationTracker, forceIfReadOnly bool) (*os.File, error) {
29162
// forceIfReadOnly is not used on this OS
30163

go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ require (
1414
github.com/mattn/go-ieproxy v0.0.3
1515
github.com/minio/minio-go v6.0.14+incompatible
1616
github.com/pkg/errors v0.9.1
17+
github.com/pkg/xattr v0.4.6
18+
github.com/rogpeppe/go-internal v1.8.1 // indirect
1719
github.com/spf13/cobra v1.4.0
1820
github.com/wastore/keychain v0.0.0-20180920053336-f2c902a3d807
1921
github.com/wastore/keyctl v0.3.1
@@ -44,7 +46,6 @@ require (
4446
github.com/kr/pretty v0.3.0 // indirect
4547
github.com/kr/text v0.2.0 // indirect
4648
github.com/mitchellh/go-homedir v1.1.0 // indirect
47-
github.com/rogpeppe/go-internal v1.8.1 // indirect
4849
github.com/russross/blackfriday/v2 v2.1.0 // indirect
4950
github.com/spf13/pflag v1.0.5 // indirect
5051
github.com/stretchr/objx v0.3.0 // indirect

go.sum

+3-9
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,9 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
5757
cloud.google.com/go/storage v1.21.0 h1:HwnT2u2D309SFDHQII6m18HlrCi3jAXhUMTLOWXYH14=
5858
cloud.google.com/go/storage v1.21.0/go.mod h1:XmRlxkgPjlBONznT2dDUU/5XlpU2OjMnKuqnZI01LAA=
5959
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
60-
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
6160
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
62-
github.com/Azure/azure-pipeline-go v0.2.4-0.20220420205509-9c760f3e9499 h1:eVXzrNOutCSxn7gYn2Tb2alO/D41vX6EyDoRhByS4zc=
63-
github.com/Azure/azure-pipeline-go v0.2.4-0.20220420205509-9c760f3e9499/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
6461
github.com/Azure/azure-pipeline-go v0.2.4-0.20220425205405-09e6f201e1e4 h1:hDJImUzpTAeIw/UasFUUDB/+UsZm5Q/6x2/jKKvEUiw=
6562
github.com/Azure/azure-pipeline-go v0.2.4-0.20220425205405-09e6f201e1e4/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
66-
github.com/Azure/azure-storage-blob-go v0.13.1-0.20220307213743-78b465951faf h1:81jHLpY81IPdZqBzsnudRpQM1E9xk+ZzBhhJm7BEvcY=
67-
github.com/Azure/azure-storage-blob-go v0.13.1-0.20220307213743-78b465951faf/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck=
68-
github.com/Azure/azure-storage-blob-go v0.13.1-0.20220418210520-914dace75d43 h1:/yh9OPVjemL4n8CaXc+GpFTvSlotRFj2HXJIgLo2gG8=
69-
github.com/Azure/azure-storage-blob-go v0.13.1-0.20220418210520-914dace75d43/go.mod h1:vbjsVbX0dlxnRc4FFMPsS9BsJWPcne7GB7onqlPvz58=
70-
github.com/Azure/azure-storage-blob-go v0.13.1-0.20220418220008-28ac0a48144e h1:uGef/l7KHdWy6XTwhnEB4IhJEisPLe0TDfLVthiVL04=
71-
github.com/Azure/azure-storage-blob-go v0.13.1-0.20220418220008-28ac0a48144e/go.mod h1:vbjsVbX0dlxnRc4FFMPsS9BsJWPcne7GB7onqlPvz58=
7263
github.com/Azure/azure-storage-blob-go v0.15.0 h1:rXtgp8tN1p29GvpGgfJetavIG0V7OgcSXPpwp3tx6qk=
7364
github.com/Azure/azure-storage-blob-go v0.15.0/go.mod h1:vbjsVbX0dlxnRc4FFMPsS9BsJWPcne7GB7onqlPvz58=
7465
github.com/Azure/azure-storage-file-go v0.6.1-0.20201111053559-3c1754dc00a5 h1:aHEvBM4oXIWSTOVdL55nCYXO0Cl7ie3Ui5xMQhLVez8=
@@ -247,6 +238,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
247238
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
248239
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
249240
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
241+
github.com/pkg/xattr v0.4.6 h1:0vqthLIMxQKA9VscyMcxjvAUGvyfzlk009vwLE8OZJg=
242+
github.com/pkg/xattr v0.4.6/go.mod h1:sBD3RAqlr8Q+RC3FutZcikpT8nyDrIEEBw2J744gVWs=
250243
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
251244
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
252245
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -437,6 +430,7 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
437430
golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
438431
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
439432
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
433+
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
440434
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
441435
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
442436
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

0 commit comments

Comments
 (0)