github.com/cs3org/reva/v2@v2.27.7/pkg/sdk/action/fileops.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 action 20 21 import ( 22 "fmt" 23 p "path" 24 "strings" 25 26 provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 27 storage "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 28 29 "github.com/cs3org/reva/v2/pkg/sdk" 30 "github.com/cs3org/reva/v2/pkg/sdk/common/net" 31 ) 32 33 // FileOperationsAction offers basic file operations. 34 type FileOperationsAction struct { 35 action 36 } 37 38 // Stat queries the file information of the specified remote resource. 39 func (action *FileOperationsAction) Stat(path string) (*storage.ResourceInfo, error) { 40 ref := &provider.Reference{Path: path} 41 req := &provider.StatRequest{Ref: ref} 42 res, err := action.session.Client().Stat(action.session.Context(), req) 43 if err := net.CheckRPCInvocation("querying resource information", res, err); err != nil { 44 return nil, err 45 } 46 return res.Info, nil 47 } 48 49 // FileExists checks whether the specified file exists. 50 func (action *FileOperationsAction) FileExists(path string) bool { 51 // Stat the file and see if that succeeds; if so, check if the resource is indeed a file 52 info, err := action.Stat(path) 53 if err != nil { 54 return false 55 } 56 return info.Type == provider.ResourceType_RESOURCE_TYPE_FILE 57 } 58 59 // DirExists checks whether the specified directory exists. 60 func (action *FileOperationsAction) DirExists(path string) bool { 61 // Stat the file and see if that succeeds; if so, check if the resource is indeed a directory 62 info, err := action.Stat(path) 63 if err != nil { 64 return false 65 } 66 return info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER 67 } 68 69 // ResourceExists checks whether the specified resource exists (w/o checking for its actual type). 70 func (action *FileOperationsAction) ResourceExists(path string) bool { 71 // Stat the file and see if that succeeds 72 _, err := action.Stat(path) 73 return err == nil 74 } 75 76 // MakePath creates the entire directory tree specified by the given path. 77 func (action *FileOperationsAction) MakePath(path string) error { 78 path = strings.TrimPrefix(path, "/") 79 80 var curPath string 81 for _, token := range strings.Split(path, "/") { 82 curPath = p.Join(curPath, "/"+token) 83 84 fileInfo, err := action.Stat(curPath) 85 if err != nil { // Stating failed, so the path probably doesn't exist yet 86 ref := &provider.Reference{Path: curPath} 87 req := &provider.CreateContainerRequest{Ref: ref} 88 res, err := action.session.Client().CreateContainer(action.session.Context(), req) 89 if err := net.CheckRPCInvocation("creating container", res, err); err != nil { 90 return err 91 } 92 } else if fileInfo.Type != provider.ResourceType_RESOURCE_TYPE_CONTAINER { 93 // The path exists, so make sure that is actually a directory 94 return fmt.Errorf("'%v' is not a directory", curPath) 95 } 96 } 97 98 return nil 99 } 100 101 // Move moves the specified source to a new location. The caller must ensure that the target directory exists. 102 func (action *FileOperationsAction) Move(source string, target string) error { 103 sourceRef := &provider.Reference{Path: source} 104 targetRef := &provider.Reference{Path: target} 105 req := &provider.MoveRequest{Source: sourceRef, Destination: targetRef} 106 res, err := action.session.Client().Move(action.session.Context(), req) 107 if err := net.CheckRPCInvocation("moving resource", res, err); err != nil { 108 return err 109 } 110 111 return nil 112 } 113 114 // MoveTo moves the specified source to the target directory, creating it if necessary. 115 func (action *FileOperationsAction) MoveTo(source string, path string) error { 116 if err := action.MakePath(path); err != nil { 117 return fmt.Errorf("unable to create the target directory '%v': %v", path, err) 118 } 119 120 path = p.Join(path, p.Base(source)) // Keep the original resource base name 121 return action.Move(source, path) 122 } 123 124 // Remove deletes the specified resource. 125 func (action *FileOperationsAction) Remove(path string) error { 126 ref := &provider.Reference{Path: path} 127 req := &provider.DeleteRequest{Ref: ref} 128 res, err := action.session.Client().Delete(action.session.Context(), req) 129 if err := net.CheckRPCInvocation("deleting resource", res, err); err != nil { 130 return err 131 } 132 133 return nil 134 } 135 136 // NewFileOperationsAction creates a new file operations action. 137 func NewFileOperationsAction(session *sdk.Session) (*FileOperationsAction, error) { 138 action := &FileOperationsAction{} 139 if err := action.initAction(session); err != nil { 140 return nil, fmt.Errorf("unable to create the FileOperationsAction: %v", err) 141 } 142 return action, nil 143 } 144 145 // MustNewFileOperationsAction creates a new file operations action and panics on failure. 146 func MustNewFileOperationsAction(session *sdk.Session) *FileOperationsAction { 147 action, err := NewFileOperationsAction(session) 148 if err != nil { 149 panic(err) 150 } 151 return action 152 }