mirror of
https://github.com/samuelncui/acp.git
synced 2026-11-08 04:21:16 +00:00
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.
68 lines
1.6 KiB
Go
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
|
|
}
|