mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
97 lines
2.3 KiB
Go
97 lines
2.3 KiB
Go
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
|
|
// Licensed under the GNU Affero General Public License (AGPL).
|
|
// See License-AGPL.txt in the project root for license information.
|
|
|
|
package quota
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
// mountPoint represents an entry in a proc mounts file
|
|
type mountPoint struct {
|
|
Device string
|
|
Path string
|
|
FS string
|
|
Opts string
|
|
}
|
|
|
|
// findmountPointFromProc calls FindmountPoint with /proc/mounts
|
|
func findMountPointFromProc(dir string) (res *mountPoint, err error) {
|
|
f, err := os.OpenFile("/proc/self/mounts", os.O_RDONLY, 0)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("cannot find mount point: %w", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
return findMountPoint(f, dir)
|
|
}
|
|
|
|
// findmountPoint finds the mount entry for a directory
|
|
func findMountPoint(mountFile io.Reader, dir string) (res *mountPoint, err error) {
|
|
res = &mountPoint{}
|
|
scanner := bufio.NewScanner(mountFile)
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
fields := strings.Fields(line)
|
|
|
|
if len(fields) < 4 {
|
|
continue
|
|
}
|
|
|
|
if mp := fields[1]; strings.HasPrefix(dir, mp) && len(mp) > len(res.Path) {
|
|
res.Device = fields[0]
|
|
res.Path = fields[1]
|
|
res.FS = fields[2]
|
|
res.Opts = fields[3]
|
|
}
|
|
}
|
|
if err = scanner.Err(); err != nil {
|
|
res = nil
|
|
return
|
|
}
|
|
if res.Path == "" {
|
|
res = nil
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// findLoopdevInLosetupOutput expects out to be the output of "losetup -a".
|
|
// It searches for lodev in that output and returns the backing filename.
|
|
// If the lodev isn't found it returns an empty string.
|
|
func findLoopdevInLosetupOutput(lodev string, out []byte) (fn string) {
|
|
lines := strings.Split(string(out), "\n")
|
|
for _, l := range lines {
|
|
fields := strings.Fields(l)
|
|
if len(fields) != 3 {
|
|
continue
|
|
}
|
|
if fields[0] != lodev+":" {
|
|
continue
|
|
}
|
|
|
|
return fields[2]
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// findLoopdevBacking runs "losetup -a" and uses findLoopdevInLosetupOutput
|
|
// to find the backing file of the lodev. If the lodev isn't found, this function
|
|
// returns an empty string and nil error.
|
|
func findLoopdevBacking(lodev string) (fn string, err error) {
|
|
out, err := exec.Command("losetup", "-a").CombinedOutput()
|
|
if err != nil {
|
|
return "", xerrors.Errorf("cannot run losetup: %w: %s", err, string(out))
|
|
}
|
|
|
|
return findLoopdevInLosetupOutput(lodev, out), nil
|
|
}
|