mirror of https://github.com/spf13/afero.git
Merge pull request #279 from mfuterko/implement-chown-functionality
Implement chown functionality
This commit is contained in:
commit
89dd0ada86
|
@ -7,6 +7,7 @@ arch:
|
|||
go:
|
||||
- "1.13"
|
||||
- "1.14"
|
||||
- "1.15"
|
||||
- tip
|
||||
|
||||
os:
|
||||
|
|
|
@ -94,6 +94,7 @@ AppFs.Open('/tmp/foo')
|
|||
File System Methods Available:
|
||||
```go
|
||||
Chmod(name string, mode os.FileMode) : error
|
||||
Chown(name string, uid, gid int) : error
|
||||
Chtimes(name string, atime time.Time, mtime time.Time) : error
|
||||
Create(name string) : File, error
|
||||
Mkdir(name string, perm os.FileMode) : error
|
||||
|
|
5
afero.go
5
afero.go
|
@ -91,9 +91,12 @@ type Fs interface {
|
|||
// The name of this FileSystem
|
||||
Name() string
|
||||
|
||||
//Chmod changes the mode of the named file to mode.
|
||||
// Chmod changes the mode of the named file to mode.
|
||||
Chmod(name string, mode os.FileMode) error
|
||||
|
||||
// Chown changes the uid and gid of the named file.
|
||||
Chown(name string, uid, gid int) error
|
||||
|
||||
//Chtimes changes the access and modification times of the named file
|
||||
Chtimes(name string, atime time.Time, mtime time.Time) error
|
||||
}
|
||||
|
|
|
@ -83,6 +83,13 @@ func (b *BasePathFs) Chmod(name string, mode os.FileMode) (err error) {
|
|||
return b.source.Chmod(name, mode)
|
||||
}
|
||||
|
||||
func (b *BasePathFs) Chown(name string, uid, gid int) (err error) {
|
||||
if name, err = b.RealPath(name); err != nil {
|
||||
return &os.PathError{Op: "chown", Path: name, Err: err}
|
||||
}
|
||||
return b.source.Chown(name, uid, gid)
|
||||
}
|
||||
|
||||
func (b *BasePathFs) Name() string {
|
||||
return "BasePathFs"
|
||||
}
|
||||
|
@ -202,5 +209,3 @@ func (b *BasePathFs) ReadlinkIfPossible(name string) (string, error) {
|
|||
}
|
||||
return "", &os.PathError{Op: "readlink", Path: name, Err: ErrNoReadlink}
|
||||
}
|
||||
|
||||
// vim: ts=4 sw=4 noexpandtab nolist syn=go
|
||||
|
|
|
@ -117,6 +117,27 @@ func (u *CacheOnReadFs) Chmod(name string, mode os.FileMode) error {
|
|||
return u.layer.Chmod(name, mode)
|
||||
}
|
||||
|
||||
func (u *CacheOnReadFs) Chown(name string, uid, gid int) error {
|
||||
st, _, err := u.cacheStatus(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch st {
|
||||
case cacheLocal:
|
||||
case cacheHit:
|
||||
err = u.base.Chown(name, uid, gid)
|
||||
case cacheStale, cacheMiss:
|
||||
if err := u.copyToLayer(name); err != nil {
|
||||
return err
|
||||
}
|
||||
err = u.base.Chown(name, uid, gid)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return u.layer.Chown(name, uid, gid)
|
||||
}
|
||||
|
||||
func (u *CacheOnReadFs) Stat(name string) (os.FileInfo, error) {
|
||||
st, fi, err := u.cacheStatus(name)
|
||||
if err != nil {
|
||||
|
|
|
@ -14,7 +14,7 @@ var _ Lstater = (*CopyOnWriteFs)(nil)
|
|||
// a possibly writeable layer on top. Changes to the file system will only
|
||||
// be made in the overlay: Changing an existing file in the base layer which
|
||||
// is not present in the overlay will copy the file to the overlay ("changing"
|
||||
// includes also calls to e.g. Chtimes() and Chmod()).
|
||||
// includes also calls to e.g. Chtimes(), Chmod() and Chown()).
|
||||
//
|
||||
// Reading directories is currently only supported via Open(), not OpenFile().
|
||||
type CopyOnWriteFs struct {
|
||||
|
@ -75,6 +75,19 @@ func (u *CopyOnWriteFs) Chmod(name string, mode os.FileMode) error {
|
|||
return u.layer.Chmod(name, mode)
|
||||
}
|
||||
|
||||
func (u *CopyOnWriteFs) Chown(name string, uid, gid int) error {
|
||||
b, err := u.isBaseFile(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b {
|
||||
if err := u.copyToLayer(name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return u.layer.Chown(name, uid, gid)
|
||||
}
|
||||
|
||||
func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) {
|
||||
fi, err := u.layer.Stat(name)
|
||||
if err != nil {
|
||||
|
|
|
@ -67,6 +67,10 @@ func (h HttpFs) Chmod(name string, mode os.FileMode) error {
|
|||
return h.source.Chmod(name, mode)
|
||||
}
|
||||
|
||||
func (h HttpFs) Chown(name string, uid, gid int) error {
|
||||
return h.source.Chown(name, uid, gid)
|
||||
}
|
||||
|
||||
func (h HttpFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||
return h.source.Chtimes(name, atime, mtime)
|
||||
}
|
||||
|
|
14
mem/file.go
14
mem/file.go
|
@ -57,6 +57,8 @@ type FileData struct {
|
|||
dir bool
|
||||
mode os.FileMode
|
||||
modtime time.Time
|
||||
uid int
|
||||
gid int
|
||||
}
|
||||
|
||||
func (d *FileData) Name() string {
|
||||
|
@ -95,6 +97,18 @@ func setModTime(f *FileData, mtime time.Time) {
|
|||
f.modtime = mtime
|
||||
}
|
||||
|
||||
func SetUID(f *FileData, uid int) {
|
||||
f.Lock()
|
||||
f.uid = uid
|
||||
f.Unlock()
|
||||
}
|
||||
|
||||
func SetGID(f *FileData, gid int) {
|
||||
f.Lock()
|
||||
f.uid = gid
|
||||
f.Unlock()
|
||||
}
|
||||
|
||||
func GetFileInfo(f *FileData) *FileInfo {
|
||||
return &FileInfo{f}
|
||||
}
|
||||
|
|
22
memmap.go
22
memmap.go
|
@ -363,6 +363,22 @@ func (m *MemMapFs) setFileMode(name string, mode os.FileMode) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *MemMapFs) Chown(name string, uid, gid int) error {
|
||||
name = normalizePath(name)
|
||||
|
||||
m.mu.RLock()
|
||||
f, ok := m.getData()[name]
|
||||
m.mu.RUnlock()
|
||||
if !ok {
|
||||
return &os.PathError{Op: "chown", Path: name, Err: ErrFileNotFound}
|
||||
}
|
||||
|
||||
mem.SetUID(f, uid)
|
||||
mem.SetGID(f, gid)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||
name = normalizePath(name)
|
||||
|
||||
|
@ -386,9 +402,3 @@ func (m *MemMapFs) List() {
|
|||
fmt.Println(x.Name(), y.Size())
|
||||
}
|
||||
}
|
||||
|
||||
// func debugMemMapList(fs Fs) {
|
||||
// if x, ok := fs.(*MemMapFs); ok {
|
||||
// x.List()
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -38,6 +38,8 @@ func TestPathErrors(t *testing.T) {
|
|||
path2 := filepath.Join(".", "different", "path")
|
||||
fs := NewMemMapFs()
|
||||
perm := os.FileMode(0755)
|
||||
uid := 1000
|
||||
gid := 1000
|
||||
|
||||
// relevant functions:
|
||||
// func (m *MemMapFs) Chmod(name string, mode os.FileMode) error
|
||||
|
@ -54,6 +56,9 @@ func TestPathErrors(t *testing.T) {
|
|||
err := fs.Chmod(path, perm)
|
||||
checkPathError(t, err, "Chmod")
|
||||
|
||||
err = fs.Chown(path, uid, gid)
|
||||
checkPathError(t, err, "Chown")
|
||||
|
||||
err = fs.Chtimes(path, time.Now(), time.Now())
|
||||
checkPathError(t, err, "Chtimes")
|
||||
|
||||
|
|
4
os.go
4
os.go
|
@ -91,6 +91,10 @@ func (OsFs) Chmod(name string, mode os.FileMode) error {
|
|||
return os.Chmod(name, mode)
|
||||
}
|
||||
|
||||
func (OsFs) Chown(name string, uid, gid int) error {
|
||||
return os.Chown(name, uid, gid)
|
||||
}
|
||||
|
||||
func (OsFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||
return os.Chtimes(name, atime, mtime)
|
||||
}
|
||||
|
|
|
@ -28,6 +28,10 @@ func (r *ReadOnlyFs) Chmod(n string, m os.FileMode) error {
|
|||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Chown(n string, uid, gid int) error {
|
||||
return syscall.EPERM
|
||||
}
|
||||
|
||||
func (r *ReadOnlyFs) Name() string {
|
||||
return "ReadOnlyFilter"
|
||||
}
|
||||
|
|
|
@ -60,6 +60,13 @@ func (r *RegexpFs) Chmod(name string, mode os.FileMode) error {
|
|||
return r.source.Chmod(name, mode)
|
||||
}
|
||||
|
||||
func (r *RegexpFs) Chown(name string, uid, gid int) error {
|
||||
if err := r.dirOrMatches(name); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.source.Chown(name, uid, gid)
|
||||
}
|
||||
|
||||
func (r *RegexpFs) Name() string {
|
||||
return "RegexpFs"
|
||||
}
|
||||
|
|
|
@ -130,6 +130,10 @@ func (s Fs) Chmod(name string, mode os.FileMode) error {
|
|||
return s.client.Chmod(name, mode)
|
||||
}
|
||||
|
||||
func (s Fs) Chown(name string, uid, gid int) error {
|
||||
return s.client.Chown(name, uid, gid)
|
||||
}
|
||||
|
||||
func (s Fs) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||
return s.client.Chtimes(name, atime, mtime)
|
||||
}
|
||||
|
|
|
@ -134,4 +134,6 @@ func (fs *Fs) Stat(name string) (os.FileInfo, error) {
|
|||
|
||||
func (fs *Fs) Chmod(name string, mode os.FileMode) error { return syscall.EROFS }
|
||||
|
||||
func (fs *Fs) Chown(name string, uid, gid int) error { return syscall.EROFS }
|
||||
|
||||
func (fs *Fs) Chtimes(name string, atime time.Time, mtime time.Time) error { return syscall.EROFS }
|
||||
|
|
|
@ -108,4 +108,6 @@ func (fs *Fs) Name() string { return "zipfs" }
|
|||
|
||||
func (fs *Fs) Chmod(name string, mode os.FileMode) error { return syscall.EPERM }
|
||||
|
||||
func (fs *Fs) Chown(name string, uid, gid int) error { return syscall.EPERM }
|
||||
|
||||
func (fs *Fs) Chtimes(name string, atime time.Time, mtime time.Time) error { return syscall.EPERM }
|
||||
|
|
Loading…
Reference in New Issue