go-hep.org/x/hep@v0.38.1/xrootd/filesystem.go (about) 1 // Copyright ©2018 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package xrootd // import "go-hep.org/x/hep/xrootd" 6 7 import ( 8 "context" 9 stdpath "path" 10 11 "go-hep.org/x/hep/xrootd/xrdfs" 12 "go-hep.org/x/hep/xrootd/xrdproto/chmod" 13 "go-hep.org/x/hep/xrootd/xrdproto/dirlist" 14 "go-hep.org/x/hep/xrootd/xrdproto/mkdir" 15 "go-hep.org/x/hep/xrootd/xrdproto/mv" 16 "go-hep.org/x/hep/xrootd/xrdproto/open" 17 "go-hep.org/x/hep/xrootd/xrdproto/rm" 18 "go-hep.org/x/hep/xrootd/xrdproto/rmdir" 19 "go-hep.org/x/hep/xrootd/xrdproto/stat" 20 "go-hep.org/x/hep/xrootd/xrdproto/statx" 21 "go-hep.org/x/hep/xrootd/xrdproto/truncate" 22 ) 23 24 // FS returns a xrdfs.FileSystem which uses this client to make requests. 25 func (cli *Client) FS() xrdfs.FileSystem { 26 return &fileSystem{cli} 27 } 28 29 // fileSystem contains filesystem-related methods of the XRootD protocol. 30 type fileSystem struct { 31 c *Client 32 } 33 34 // Dirlist returns the contents of a directory together with the stat information. 35 func (fs *fileSystem) Dirlist(ctx context.Context, path string) ([]xrdfs.EntryStat, error) { 36 var resp dirlist.Response 37 _, err := fs.c.Send(ctx, &resp, dirlist.NewRequest(path)) 38 if err != nil { 39 return nil, err 40 } 41 return resp.Entries, err 42 } 43 44 // Open returns the file handle for a file together with the compression and the stat info. 45 func (fs *fileSystem) Open(ctx context.Context, path string, mode xrdfs.OpenMode, options xrdfs.OpenOptions) (xrdfs.File, error) { 46 var resp open.Response 47 server, err := fs.c.Send(ctx, &resp, open.NewRequest(path, mode, options)) 48 if err != nil { 49 return nil, err 50 } 51 return &file{fs: fs, handle: resp.FileHandle, compression: resp.Compression, info: resp.Stat, sessionID: server}, nil 52 } 53 54 // RemoveFile removes a file. 55 func (fs *fileSystem) RemoveFile(ctx context.Context, path string) error { 56 _, err := fs.c.Send(ctx, nil, &rm.Request{Path: path}) 57 return err 58 } 59 60 // Truncate changes the size of the named file. 61 func (fs *fileSystem) Truncate(ctx context.Context, path string, size int64) error { 62 _, err := fs.c.Send(ctx, nil, &truncate.Request{Path: path, Size: size}) 63 return err 64 } 65 66 // Stat returns the entry stat info for the given path. 67 func (fs *fileSystem) Stat(ctx context.Context, path string) (xrdfs.EntryStat, error) { 68 var resp stat.DefaultResponse 69 _, err := fs.c.Send(ctx, &resp, &stat.Request{Path: path}) 70 if err != nil { 71 return xrdfs.EntryStat{}, err 72 } 73 return resp.EntryStat, nil 74 } 75 76 // VirtualStat returns the virtual filesystem stat info for the given path. 77 // Note that path needs not to be an existing filesystem object, it is used as a path prefix in order to 78 // filter out servers and partitions that could not be used to hold objects whose path starts 79 // with the specified path prefix. 80 func (fs *fileSystem) VirtualStat(ctx context.Context, path string) (xrdfs.VirtualFSStat, error) { 81 var resp stat.VirtualFSResponse 82 _, err := fs.c.Send(ctx, &resp, &stat.Request{Path: path, Options: stat.OptionsVFS}) 83 if err != nil { 84 return xrdfs.VirtualFSStat{}, err 85 } 86 return resp.VirtualFSStat, nil 87 } 88 89 // Mkdir creates a new directory with the specified name and permission bits. 90 func (fs *fileSystem) Mkdir(ctx context.Context, path string, perm xrdfs.OpenMode) error { 91 _, err := fs.c.Send(ctx, nil, &mkdir.Request{Path: path, Mode: perm}) 92 return err 93 } 94 95 // MkdirAll creates a directory named path, along with any necessary parents, 96 // and returns nil, or else returns an error. 97 // The permission bits perm are used for all directories that MkdirAll creates. 98 func (fs *fileSystem) MkdirAll(ctx context.Context, path string, perm xrdfs.OpenMode) error { 99 _, err := fs.c.Send(ctx, nil, &mkdir.Request{Path: path, Mode: perm, Options: mkdir.OptionsMakePath}) 100 return err 101 } 102 103 // RemoveDir removes a directory. 104 // The directory to be removed must be empty. 105 func (fs *fileSystem) RemoveDir(ctx context.Context, path string) error { 106 _, err := fs.c.Send(ctx, nil, &rmdir.Request{Path: path}) 107 return err 108 } 109 110 // RemoveAll removes path and any children it contains. 111 // It removes everything it can but returns the first error it encounters. 112 // If the path does not exist, RemoveAll returns nil (no error.) 113 func (fs *fileSystem) RemoveAll(ctx context.Context, path string) error { 114 st, err := fs.Stat(ctx, path) 115 if err != nil { 116 return err 117 } 118 switch { 119 case st.IsDir(): 120 entries, err := fs.Dirlist(ctx, path) 121 if err != nil { 122 return err 123 } 124 for _, e := range entries { 125 name := stdpath.Join(path, e.Name()) 126 err := fs.RemoveAll(ctx, name) 127 if err != nil { 128 return err 129 } 130 } 131 return fs.RemoveDir(ctx, path) 132 default: 133 return fs.RemoveFile(ctx, path) 134 } 135 } 136 137 // Rename renames (moves) oldpath to newpath. 138 func (fs *fileSystem) Rename(ctx context.Context, oldpath, newpath string) error { 139 _, err := fs.c.Send(ctx, nil, &mv.Request{OldPath: oldpath, NewPath: newpath}) 140 return err 141 } 142 143 // Chmod changes the permissions of the named file to perm. 144 func (fs *fileSystem) Chmod(ctx context.Context, path string, perm xrdfs.OpenMode) error { 145 _, err := fs.c.Send(ctx, nil, &chmod.Request{Path: path, Mode: perm}) 146 return err 147 } 148 149 // Statx obtains type information for one or more paths. 150 // Only a limited number of flags is meaningful such as StatIsExecutable, StatIsDir, StatIsOther, StatIsOffline. 151 func (fs *fileSystem) Statx(ctx context.Context, paths []string) ([]xrdfs.StatFlags, error) { 152 var resp statx.Response 153 _, err := fs.c.Send(ctx, &resp, statx.NewRequest(paths)) 154 if err != nil { 155 return nil, err 156 } 157 return resp.StatFlags, nil 158 } 159 160 var ( 161 _ xrdfs.FileSystem = (*fileSystem)(nil) 162 )