fix: don't follow symlinks in disk usage

pull/3756/head
Laurynas Gadliauskas 2021-06-17 13:40:42 +03:00
parent d9aaa551a2
commit d5ca315102
4 changed files with 24 additions and 46 deletions

View File

@ -62,8 +62,13 @@ func CopyDir(fs afero.Fs, source, dest string) error {
return nil return nil
} }
func DiskUsage(fs afero.Fs, path string, maxDepth int) (size, inodes int64, err error) { func DiskUsage(fs afero.Fs, path string) (size, inodes int64, err error) {
info, err := fs.Stat(path) lst, ok := fs.(afero.Lstater)
if !ok {
return 0, 0, err
}
info, _, err := lst.LstatIfPossible(path)
if err != nil { if err != nil {
return 0, 0, err return 0, 0, err
} }
@ -71,36 +76,24 @@ func DiskUsage(fs afero.Fs, path string, maxDepth int) (size, inodes int64, err
size = info.Size() size = info.Size()
inodes = int64(1) inodes = int64(1)
// don't follow symlinks
if !info.IsDir() { if !info.IsDir() {
return size, inodes, err return size, inodes, err
} }
if maxDepth < 1 { afs := &afero.Afero{Fs: fs}
return size, inodes, err dir, err := afs.ReadDir(path)
}
dir, err := fs.Open(path)
if err != nil {
return size, inodes, err
}
defer dir.Close()
fis, err := dir.Readdir(-1)
if err != nil { if err != nil {
return size, inodes, err return size, inodes, err
} }
for _, fi := range fis { for _, fi := range dir {
if fi.Name() == "." || fi.Name() == ".." { s, i, e := DiskUsage(fs, filepath.Join(path, fi.Name()))
continue if e == nil {
}
s, i, e := DiskUsage(fs, filepath.Join(path, fi.Name()), maxDepth-1)
if e != nil {
return size, inodes, e
}
size += s size += s
inodes += i inodes += i
} }
}
return size, inodes, err return size, inodes, err
} }

View File

@ -52,7 +52,7 @@ func TestDiskUsageOnFile(t *testing.T) {
} }
fs := afero.NewBasePathFs(afero.NewOsFs(), cwd) fs := afero.NewBasePathFs(afero.NewOsFs(), cwd)
size, inodes, err := DiskUsage(fs, filepath.Join(RootTestDir, "test_file"), 100) size, inodes, err := DiskUsage(fs, filepath.Join(RootTestDir, "test_file"))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, int64(9), size) require.Equal(t, int64(9), size)
@ -72,7 +72,7 @@ func TestDiskUsageOnNestedDir(t *testing.T) {
} }
fs := afero.NewBasePathFs(afero.NewOsFs(), cwd) fs := afero.NewBasePathFs(afero.NewOsFs(), cwd)
size, inodes, err := DiskUsage(fs, filepath.Join(RootTestDir, "child_dir"), 100) size, inodes, err := DiskUsage(fs, filepath.Join(RootTestDir, "child_dir"))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, int64(105), size) require.Equal(t, int64(105), size)
@ -92,29 +92,9 @@ func TestDiskUsageOnRootDir(t *testing.T) {
} }
fs := afero.NewBasePathFs(afero.NewOsFs(), cwd) fs := afero.NewBasePathFs(afero.NewOsFs(), cwd)
size, inodes, err := DiskUsage(fs, RootTestDir, 100) size, inodes, err := DiskUsage(fs, RootTestDir)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, int64(242), size) require.Equal(t, int64(242), size)
require.Equal(t, int64(4), inodes) require.Equal(t, int64(4), inodes)
} }
func TestDiskUsageOnRootDirStopsAtDepthLimit(t *testing.T) {
err := createFileStructure()
if err != nil {
t.Errorf("createFileStructure() failed: %s", err)
}
defer cleanupFileStructure()
cwd, err := os.Getwd()
if err != nil {
t.Errorf("Getwd() failed: %s", err)
}
fs := afero.NewBasePathFs(afero.NewOsFs(), cwd)
size, inodes, err := DiskUsage(fs, RootTestDir, 1)
require.NoError(t, err)
require.Equal(t, int64(233), size)
require.Equal(t, int64(3), inodes)
}

View File

@ -1,4 +1,5 @@
import { users as api } from "@/api"; import { users as api } from "@/api";
import { quotaExists } from "@/utils/constants";
const state = { const state = {
inodes: null, inodes: null,
@ -14,6 +15,10 @@ const mutations = {
const actions = { const actions = {
fetch: async (context, delay = 0) => { fetch: async (context, delay = 0) => {
if (!quotaExists) {
return;
}
setTimeout(async () => { setTimeout(async () => {
try { try {
let data = await api.getQuota(); let data = await api.getQuota();

View File

@ -43,7 +43,7 @@ var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d
} }
if r.URL.Query().Get("disk_usage") == "true" { if r.URL.Query().Get("disk_usage") == "true" {
du, inodes, err := fileutils.DiskUsage(file.Fs, file.Path, 100) du, inodes, err := fileutils.DiskUsage(file.Fs, file.Path)
if err != nil { if err != nil {
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
} }