Rewrite the file/dir chowing to be less intense on the system and use walker function

This commit is contained in:
Dane Everitt 2020-07-31 22:06:00 -07:00
parent 64df3e168f
commit ecb2cb05ce
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53

View File

@ -463,70 +463,46 @@ func (fs *Filesystem) Rename(from string, to string) error {
return os.Rename(cleanedFrom, cleanedTo) return os.Rename(cleanedFrom, cleanedTo)
} }
// Recursively iterates over a directory and sets the permissions on all of the // Recursively iterates over a file or directory and sets the permissions on all of the
// underlying files. // underlying files. Iterate over all of the files and directories. If it is a file just
// go ahead and perform the chown operation. Otherwise dig deeper into the directory until
// we've run out of directories to dig into.
func (fs *Filesystem) Chown(path string) error { func (fs *Filesystem) Chown(path string) error {
cleaned, err := fs.SafePath(path) cleaned, err := fs.SafePath(path)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
if s, err := os.Stat(cleaned); err != nil { uid := config.Get().System.User.Uid
gid := config.Get().System.User.Gid
// Start by just chowning the initial path that we received.
if err := os.Chown(cleaned, uid, gid); err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} else if !s.IsDir() {
return os.Chown(cleaned, config.Get().System.User.Uid, config.Get().System.User.Gid)
} }
return fs.chownDirectory(cleaned) // If this is not a directory we can now return from the function, there is nothing
} // left that we need to do.
if st, _ := os.Stat(cleaned); !st.IsDir() {
return nil
}
// Iterate over all of the files and directories. If it is a file just go ahead and perform // If this was a directory, begin walking over its contents recursively and ensure that all
// the chown operation. Otherwise dig deeper into the directory until we've run out of // of the subfiles and directories get their permissions updated as well.
// directories to dig into. return fs.Walk(cleaned, func(path string, f os.FileInfo, err error) error {
func (fs *Filesystem) chownDirectory(path string) error {
var wg sync.WaitGroup
cleaned, err := fs.SafePath(path)
if err != nil { if err != nil {
return errors.WithStack(err) return fs.handleWalkerError(err, f)
} }
// Chown the directory itself.
os.Chown(cleaned, config.Get().System.User.Uid, config.Get().System.User.Gid)
files, err := ioutil.ReadDir(cleaned)
if err != nil {
return errors.WithStack(err)
}
for _, f := range files {
// Do not attempt to chmod a symlink. Go's os.Chown function will affect the symlink // Do not attempt to chmod a symlink. Go's os.Chown function will affect the symlink
// so if it points to a location outside the data directory the user would be able to // so if it points to a location outside the data directory the user would be able to
// (un)intentionally modify that files permissions. // (un)intentionally modify that files permissions.
if f.Mode()&os.ModeSymlink != 0 { if f.Mode()&os.ModeSymlink != 0 {
continue
}
p, err := fs.SafeJoin(cleaned, f)
if err != nil {
return err
}
if f.IsDir() {
wg.Add(1)
go func(p string) {
defer wg.Done()
fs.chownDirectory(p)
}(p)
} else {
os.Chown(p, config.Get().System.User.Uid, config.Get().System.User.Gid)
}
}
wg.Wait()
return nil return nil
}
return os.Chown(path, uid, gid)
})
} }
// Copies a given file to the same location and appends a suffix to the file to indicate that // Copies a given file to the same location and appends a suffix to the file to indicate that