@@ -26,6 +26,7 @@ import (
26
26
"github.com/Azure/azure-storage-blob-go/azblob"
27
27
"net/url"
28
28
"strings"
29
+ "sync"
29
30
"time"
30
31
31
32
"github.com/Azure/azure-pipeline-go/pipeline"
@@ -237,7 +238,9 @@ func (u *blobFSSenderBase) GetSourcePOSIXProperties() (common.UnixStatAdapter, e
237
238
}
238
239
}
239
240
240
- func (u * blobFSSenderBase ) SetPOSIXProperties () error {
241
+ var HNSSetAccessControlFailedOnce = & sync.Once {}
242
+
243
+ func (u * blobFSSenderBase ) SetPOSIXProperties (hnsOnly bool ) error {
241
244
adapter , err := u .GetSourcePOSIXProperties ()
242
245
if err != nil {
243
246
return fmt .Errorf ("failed to get POSIX properties" )
@@ -249,12 +252,57 @@ func (u *blobFSSenderBase) SetPOSIXProperties() error {
249
252
common .AddStatToBlobMetadata (adapter , meta )
250
253
delete (meta , common .POSIXFolderMeta ) // Can't be set on HNS accounts.
251
254
252
- _ , err = u .GetBlobURL ().SetMetadata (u .jptm .Context (), meta , azblob.BlobAccessConditions {}, azblob.ClientProvidedKeyOptions {})
253
- return err
255
+ var AccessControlURL interface {SetAccessControl (ctx context.Context , permissions azbfs.BlobFSAccessControl ) (* azbfs.PathUpdateResponse , error )}
256
+ switch u .SendableEntityType () {
257
+ case common .EEntityType .File (), common .EEntityType .Symlink ():
258
+ AccessControlURL = u .fileURL ()
259
+ case common .EEntityType .Folder ():
260
+ AccessControlURL = u .dirURL ()
261
+ }
262
+
263
+ isRoot := false
264
+ if dURL , ok := AccessControlURL .(azbfs.DirectoryURL ); ok {
265
+ if dURL .IsFileSystemRoot () {
266
+ isRoot = true
267
+ }
268
+ }
269
+
270
+ if ! hnsOnly && ! isRoot { // don't try to set metadata on the container
271
+ _ , err = u .GetBlobURL ().SetMetadata (u .jptm .Context (), meta , azblob.BlobAccessConditions {}, azblob.ClientProvidedKeyOptions {})
272
+ if err != nil {
273
+ return err
274
+ }
275
+ }
276
+
277
+ mode := adapter .FileMode ()
278
+ fields := []uint32 {common .S_IRUSR , common .S_IWUSR , common .S_IXUSR , common .S_IRGRP , common .S_IWGRP , common .S_IXGRP , common .S_IROTH , common .S_IWOTH , common .S_IXOTH }
279
+ chars := "rwx"
280
+ out := ""
281
+ for _ , field := range fields {
282
+ if mode & field == field {
283
+ out += string (chars [len (out ) % 3 ])
284
+ } else {
285
+ out += "-"
286
+ }
287
+ }
288
+
289
+ _ , err = AccessControlURL .SetAccessControl (u .jptm .Context (), azbfs.BlobFSAccessControl {
290
+ Owner : fmt .Sprint (adapter .Owner ()),
291
+ Group : fmt .Sprint (adapter .Group ()),
292
+ Permissions : out ,
293
+ })
294
+ if err != nil { // A user could be targeting a non-HNS account with the dfs endpoint; it's best to warn rather than fail.
295
+ u .jptm .LogAtLevelForCurrentTransfer (pipeline .LogError , fmt .Sprintf ("Failed to set dfs owner/group: %s" , err .Error ()))
296
+ HNSSetAccessControlFailedOnce .Do (func () {
297
+ common .GetLifecycleMgr ().Info ("One or more files or directories have failed to set access control; check the logs for details. (are you targeting a non-HNS account?)" )
298
+ })
299
+ }
300
+
301
+ return nil
254
302
}
255
303
256
304
func (u * blobFSSenderBase ) SetFolderProperties () error {
257
- return u .SetPOSIXProperties ()
305
+ return u .SetPOSIXProperties (false )
258
306
}
259
307
260
308
func (u * blobFSSenderBase ) DirUrlToString () string {
@@ -295,6 +343,9 @@ func (u *blobFSSenderBase) SendSymlink(linkData string) error {
295
343
nil , // dfs doesn't support tags
296
344
azblob.ClientProvidedKeyOptions {}, // cpk isn't used for dfs
297
345
azblob.ImmutabilityPolicyOptions {}) // dfs doesn't support immutability policy
346
+ if err != nil {
347
+ return err
348
+ }
298
349
299
- return err
350
+ return u . SetPOSIXProperties ( true ) // set only the HNS props
300
351
}
0 commit comments