github.com/cs3org/reva/v2@v2.27.7/pkg/storage/utils/decomposedfs/node/xattrs.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package node 20 21 import ( 22 "context" 23 "io" 24 "io/fs" 25 "strconv" 26 "time" 27 28 "github.com/pkg/xattr" 29 ) 30 31 // Attributes is a map of string keys and byte array values 32 type Attributes map[string][]byte 33 34 // String reads a String value 35 func (md Attributes) String(key string) string { 36 return string(md[key]) 37 } 38 39 // SetString sets a string value 40 func (md Attributes) SetString(key, val string) { 41 md[key] = []byte(val) 42 } 43 44 // Int64 reads an int64 value 45 func (md Attributes) Int64(key string) (int64, error) { 46 return strconv.ParseInt(string(md[key]), 10, 64) 47 } 48 49 // SetInt64 sets an int64 value 50 func (md Attributes) SetInt64(key string, val int64) { 51 md[key] = []byte(strconv.FormatInt(val, 10)) 52 } 53 54 // UInt64 reads an uint64 value 55 func (md Attributes) UInt64(key string) (uint64, error) { 56 return strconv.ParseUint(string(md[key]), 10, 64) 57 } 58 59 // SetInt64 sets an uint64 value 60 func (md Attributes) SetUInt64(key string, val uint64) { 61 md[key] = []byte(strconv.FormatUint(val, 10)) 62 } 63 64 // Time reads a time value 65 func (md Attributes) Time(key string) (time.Time, error) { 66 return time.Parse(time.RFC3339Nano, string(md[key])) 67 } 68 69 // SetXattrs sets multiple extended attributes on the write-through cache/node 70 func (n *Node) SetXattrsWithContext(ctx context.Context, attribs map[string][]byte, acquireLock bool) (err error) { 71 _, span := tracer.Start(ctx, "SetXattrsWithContext") 72 defer span.End() 73 if n.xattrsCache != nil { 74 for k, v := range attribs { 75 n.xattrsCache[k] = v 76 } 77 } 78 79 return n.lu.MetadataBackend().SetMultiple(ctx, n.InternalPath(), attribs, acquireLock) 80 } 81 82 // SetXattrs sets multiple extended attributes on the write-through cache/node 83 func (n *Node) SetXattrs(attribs map[string][]byte, acquireLock bool) (err error) { 84 return n.SetXattrsWithContext(context.Background(), attribs, acquireLock) 85 } 86 87 // SetXattr sets an extended attribute on the write-through cache/node 88 func (n *Node) SetXattr(ctx context.Context, key string, val []byte) (err error) { 89 if n.xattrsCache != nil { 90 n.xattrsCache[key] = val 91 } 92 93 return n.lu.MetadataBackend().Set(ctx, n.InternalPath(), key, val) 94 } 95 96 // SetXattrString sets a string extended attribute on the write-through cache/node 97 func (n *Node) SetXattrString(ctx context.Context, key, val string) (err error) { 98 if n.xattrsCache != nil { 99 n.xattrsCache[key] = []byte(val) 100 } 101 102 return n.lu.MetadataBackend().Set(ctx, n.InternalPath(), key, []byte(val)) 103 } 104 105 // RemoveXattr removes an extended attribute from the write-through cache/node 106 func (n *Node) RemoveXattr(ctx context.Context, key string, acquireLock bool) error { 107 if n.xattrsCache != nil { 108 delete(n.xattrsCache, key) 109 } 110 return n.lu.MetadataBackend().Remove(ctx, n.InternalPath(), key, acquireLock) 111 } 112 113 // XattrsWithReader returns the extended attributes of the node. If the attributes have already 114 // been cached they are not read from disk again. 115 func (n *Node) XattrsWithReader(ctx context.Context, r io.Reader) (Attributes, error) { 116 if n.ID == "" { 117 // Do not try to read the attribute of an empty node. The InternalPath points to the 118 // base nodes directory in this case. 119 return Attributes{}, &xattr.Error{Op: "node.XattrsWithReader", Path: n.InternalPath(), Err: xattr.ENOATTR} 120 } 121 122 if n.xattrsCache != nil { 123 return n.xattrsCache, nil 124 } 125 126 var attrs Attributes 127 var err error 128 if r != nil { 129 attrs, err = n.lu.MetadataBackend().AllWithLockedSource(ctx, n.InternalPath(), r) 130 } else { 131 attrs, err = n.lu.MetadataBackend().All(ctx, n.InternalPath()) 132 } 133 if err != nil { 134 return nil, err 135 } 136 137 n.xattrsCache = attrs 138 return n.xattrsCache, nil 139 } 140 141 // Xattrs returns the extended attributes of the node. If the attributes have already 142 // been cached they are not read from disk again. 143 func (n *Node) Xattrs(ctx context.Context) (Attributes, error) { 144 return n.XattrsWithReader(ctx, nil) 145 } 146 147 // Xattr returns an extended attribute of the node. If the attributes have already 148 // been cached it is not read from disk again. 149 func (n *Node) Xattr(ctx context.Context, key string) ([]byte, error) { 150 path := n.InternalPath() 151 152 if path == "" { 153 // Do not try to read the attribute of an non-existing node 154 return []byte{}, fs.ErrNotExist 155 } 156 157 if n.ID == "" { 158 // Do not try to read the attribute of an empty node. The InternalPath points to the 159 // base nodes directory in this case. 160 return []byte{}, &xattr.Error{Op: "node.Xattr", Path: path, Name: key, Err: xattr.ENOATTR} 161 } 162 163 if n.xattrsCache == nil { 164 attrs, err := n.lu.MetadataBackend().All(ctx, path) 165 if err != nil { 166 return []byte{}, err 167 } 168 n.xattrsCache = attrs 169 } 170 171 if val, ok := n.xattrsCache[key]; ok { 172 return val, nil 173 } 174 // wrap the error as xattr does 175 return []byte{}, &xattr.Error{Op: "node.Xattr", Path: path, Name: key, Err: xattr.ENOATTR} 176 } 177 178 // XattrString returns the string representation of an attribute 179 func (n *Node) XattrString(ctx context.Context, key string) (string, error) { 180 b, err := n.Xattr(ctx, key) 181 if err != nil { 182 return "", err 183 } 184 return string(b), nil 185 } 186 187 // XattrInt32 returns the int32 representation of an attribute 188 func (n *Node) XattrInt32(ctx context.Context, key string) (int32, error) { 189 b, err := n.XattrString(ctx, key) 190 if err != nil { 191 return 0, err 192 } 193 194 typeInt, err := strconv.ParseInt(b, 10, 32) 195 if err != nil { 196 return 0, err 197 } 198 return int32(typeInt), nil 199 } 200 201 // XattrInt64 returns the int64 representation of an attribute 202 func (n *Node) XattrInt64(ctx context.Context, key string) (int64, error) { 203 b, err := n.XattrString(ctx, key) 204 if err != nil { 205 return 0, err 206 } 207 return strconv.ParseInt(b, 10, 64) 208 } 209 210 // XattrUint64 returns the uint64 representation of an attribute 211 func (n *Node) XattrUint64(ctx context.Context, key string) (uint64, error) { 212 b, err := n.XattrString(ctx, key) 213 if err != nil { 214 return 0, err 215 } 216 return strconv.ParseUint(b, 10, 64) 217 }