Files
acp/disk_usage.go
T
Samuel Cui 4d5dbd0b8c Release ACP v0.2.3
Simplify indexed copy facts and unify staged output completion.
Fix cleanup, rewrite persistence, native paths, and terminal reporting.
Maintain compatibility, upstream notices, and automated release checks.
2026-10-05 16:29:55 +08:00

68 lines
1.6 KiB
Go

package acp
import (
"errors"
"fmt"
"syscall"
"github.com/samuelncui/godf"
)
var (
ErrTargetNoSpace = fmt.Errorf("acp: target have no space")
ErrTargetDropToReadonly = fmt.Errorf("acp: target droped into readonly")
// ErrTargetIO reports an I/O failure of one target. Unlike ErrTargetDropToReadonly it does
// not describe the whole device, so it must not abort a target that is still writable.
ErrTargetIO = fmt.Errorf("acp: target have io error")
errorMapping = []errorPair{
{from: syscall.ENOSPC, to: ErrTargetNoSpace},
{from: syscall.EROFS, to: ErrTargetDropToReadonly},
{from: syscall.EIO, to: ErrTargetIO},
}
abortErrors = []error{
ErrTargetNoSpace,
ErrTargetDropToReadonly,
}
)
type errorPair struct {
from error
to error
}
// availableSpace is queried just before a linear target starts writing. Ordinary targets
// rely on real allocation and write errors instead of a second capacity estimate.
func availableSpace(mountPoint string) (int64, error) {
usage, err := godf.NewDiskUsage(mountPoint)
if err != nil {
return 0, fmt.Errorf("get disk usage failed, mount=%q, %w", mountPoint, err)
}
return usage.Available(), nil
}
func mappingError(err error) error {
if err == nil {
return nil
}
// A cleanup error may have a different identity from the primary I/O failure.
for _, p := range errorMapping {
if errors.Is(err, p.from) && !errors.Is(err, p.to) {
err = errors.Join(p.to, err)
}
}
return err
}
func checkErrorAbort(err error) bool {
for _, e := range abortErrors {
if errors.Is(err, e) {
return true
}
}
return false
}