forked from mirror/afero
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:
|
go:
|
||||||
- "1.13"
|
- "1.13"
|
||||||
- "1.14"
|
- "1.14"
|
||||||
|
- "1.15"
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
os:
|
os:
|
||||||
|
|
|
@ -94,6 +94,7 @@ AppFs.Open('/tmp/foo')
|
||||||
File System Methods Available:
|
File System Methods Available:
|
||||||
```go
|
```go
|
||||||
Chmod(name string, mode os.FileMode) : error
|
Chmod(name string, mode os.FileMode) : error
|
||||||
|
Chown(name string, uid, gid int) : error
|
||||||
Chtimes(name string, atime time.Time, mtime time.Time) : error
|
Chtimes(name string, atime time.Time, mtime time.Time) : error
|
||||||
Create(name string) : File, error
|
Create(name string) : File, error
|
||||||
Mkdir(name string, perm os.FileMode) : 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
|
// The name of this FileSystem
|
||||||
Name() string
|
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
|
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 changes the access and modification times of the named file
|
||||||
Chtimes(name string, atime time.Time, mtime time.Time) error
|
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)
|
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 {
|
func (b *BasePathFs) Name() string {
|
||||||
return "BasePathFs"
|
return "BasePathFs"
|
||||||
}
|
}
|
||||||
|
@ -202,5 +209,3 @@ func (b *BasePathFs) ReadlinkIfPossible(name string) (string, error) {
|
||||||
}
|
}
|
||||||
return "", &os.PathError{Op: "readlink", Path: name, Err: ErrNoReadlink}
|
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)
|
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) {
|
func (u *CacheOnReadFs) Stat(name string) (os.FileInfo, error) {
|
||||||
st, fi, err := u.cacheStatus(name)
|
st, fi, err := u.cacheStatus(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -14,7 +14,7 @@ var _ Lstater = (*CopyOnWriteFs)(nil)
|
||||||
// a possibly writeable layer on top. Changes to the file system will only
|
// 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
|
// 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"
|
// 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().
|
// Reading directories is currently only supported via Open(), not OpenFile().
|
||||||
type CopyOnWriteFs struct {
|
type CopyOnWriteFs struct {
|
||||||
|
@ -75,6 +75,19 @@ func (u *CopyOnWriteFs) Chmod(name string, mode os.FileMode) error {
|
||||||
return u.layer.Chmod(name, mode)
|
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) {
|
func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) {
|
||||||
fi, err := u.layer.Stat(name)
|
fi, err := u.layer.Stat(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -67,6 +67,10 @@ func (h HttpFs) Chmod(name string, mode os.FileMode) error {
|
||||||
return h.source.Chmod(name, mode)
|
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 {
|
func (h HttpFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||||
return h.source.Chtimes(name, atime, mtime)
|
return h.source.Chtimes(name, atime, mtime)
|
||||||
}
|
}
|
||||||
|
|
14
mem/file.go
14
mem/file.go
|
@ -57,6 +57,8 @@ type FileData struct {
|
||||||
dir bool
|
dir bool
|
||||||
mode os.FileMode
|
mode os.FileMode
|
||||||
modtime time.Time
|
modtime time.Time
|
||||||
|
uid int
|
||||||
|
gid int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *FileData) Name() string {
|
func (d *FileData) Name() string {
|
||||||
|
@ -95,6 +97,18 @@ func setModTime(f *FileData, mtime time.Time) {
|
||||||
f.modtime = mtime
|
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 {
|
func GetFileInfo(f *FileData) *FileInfo {
|
||||||
return &FileInfo{f}
|
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
|
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 {
|
func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||||
name = normalizePath(name)
|
name = normalizePath(name)
|
||||||
|
|
||||||
|
@ -386,9 +402,3 @@ func (m *MemMapFs) List() {
|
||||||
fmt.Println(x.Name(), y.Size())
|
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")
|
path2 := filepath.Join(".", "different", "path")
|
||||||
fs := NewMemMapFs()
|
fs := NewMemMapFs()
|
||||||
perm := os.FileMode(0755)
|
perm := os.FileMode(0755)
|
||||||
|
uid := 1000
|
||||||
|
gid := 1000
|
||||||
|
|
||||||
// relevant functions:
|
// relevant functions:
|
||||||
// func (m *MemMapFs) Chmod(name string, mode os.FileMode) error
|
// func (m *MemMapFs) Chmod(name string, mode os.FileMode) error
|
||||||
|
@ -54,6 +56,9 @@ func TestPathErrors(t *testing.T) {
|
||||||
err := fs.Chmod(path, perm)
|
err := fs.Chmod(path, perm)
|
||||||
checkPathError(t, err, "Chmod")
|
checkPathError(t, err, "Chmod")
|
||||||
|
|
||||||
|
err = fs.Chown(path, uid, gid)
|
||||||
|
checkPathError(t, err, "Chown")
|
||||||
|
|
||||||
err = fs.Chtimes(path, time.Now(), time.Now())
|
err = fs.Chtimes(path, time.Now(), time.Now())
|
||||||
checkPathError(t, err, "Chtimes")
|
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)
|
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 {
|
func (OsFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||||
return os.Chtimes(name, atime, mtime)
|
return os.Chtimes(name, atime, mtime)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,10 @@ func (r *ReadOnlyFs) Chmod(n string, m os.FileMode) error {
|
||||||
return syscall.EPERM
|
return syscall.EPERM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ReadOnlyFs) Chown(n string, uid, gid int) error {
|
||||||
|
return syscall.EPERM
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ReadOnlyFs) Name() string {
|
func (r *ReadOnlyFs) Name() string {
|
||||||
return "ReadOnlyFilter"
|
return "ReadOnlyFilter"
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,13 @@ func (r *RegexpFs) Chmod(name string, mode os.FileMode) error {
|
||||||
return r.source.Chmod(name, mode)
|
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 {
|
func (r *RegexpFs) Name() string {
|
||||||
return "RegexpFs"
|
return "RegexpFs"
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,10 @@ func (s Fs) Chmod(name string, mode os.FileMode) error {
|
||||||
return s.client.Chmod(name, mode)
|
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 {
|
func (s Fs) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||||
return s.client.Chtimes(name, atime, mtime)
|
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) 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 }
|
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) 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 }
|
func (fs *Fs) Chtimes(name string, atime time.Time, mtime time.Time) error { return syscall.EPERM }
|
||||||
|
|
Loading…
Reference in New Issue