cmd/kgz: linter fixes.
This commit is contained in:
@@ -8,12 +8,14 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
goutilslib "git.wntrmute.dev/kyle/goutils/lib"
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
goutilslib "git.wntrmute.dev/kyle/goutils/lib"
|
||||||
)
|
)
|
||||||
|
|
||||||
const gzipExt = ".gz"
|
const gzipExt = ".gz"
|
||||||
@@ -59,16 +61,61 @@ func buildKGExtra(uid, gid, mode uint32, ctimeS int64, ctimeNs int32) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wrap in gzip subfield: [ID1 ID2 LEN(lo) LEN(hi) PAYLOAD]
|
// Wrap in gzip subfield: [ID1 ID2 LEN(lo) LEN(hi) PAYLOAD]
|
||||||
|
// Guard against payload length overflow to uint16 for the extra subfield length.
|
||||||
|
if len(payload) > int(math.MaxUint16) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
extra := make([]byte, 4+len(payload))
|
extra := make([]byte, 4+len(payload))
|
||||||
extra[0] = kgzExtraID[0]
|
extra[0] = kgzExtraID[0]
|
||||||
extra[1] = kgzExtraID[1]
|
extra[1] = kgzExtraID[1]
|
||||||
binary.LittleEndian.PutUint16(extra[2:], uint16(len(payload)))
|
binary.LittleEndian.PutUint16(extra[2:], uint16(len(payload)&0xFFFF)) //#nosec G115 - masked
|
||||||
copy(extra[4:], payload)
|
copy(extra[4:], payload)
|
||||||
return extra
|
return extra
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clampToInt32 clamps an int value into the int32 range using a switch to
|
||||||
|
// satisfy linters that prefer switch over if-else chains for ordered checks.
|
||||||
|
func clampToInt32(v int) int32 {
|
||||||
|
switch {
|
||||||
|
case v > int(math.MaxInt32):
|
||||||
|
return math.MaxInt32
|
||||||
|
case v < int(math.MinInt32):
|
||||||
|
return math.MinInt32
|
||||||
|
default:
|
||||||
|
return int32(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildExtraForPath prepares the gzip Extra field for kgz by collecting
|
||||||
|
// uid/gid/mode and ctime information, applying any overrides, and encoding it.
|
||||||
|
func buildExtraForPath(st unix.Stat_t, path string, setUID, setGID int) []byte {
|
||||||
|
uid := st.Uid
|
||||||
|
gid := st.Gid
|
||||||
|
if setUID >= 0 {
|
||||||
|
if uint64(setUID) <= math.MaxUint32 {
|
||||||
|
uid = uint32(setUID & 0xFFFFFFFF) //#nosec G115 - masked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if setGID >= 0 {
|
||||||
|
if uint64(setGID) <= math.MaxUint32 {
|
||||||
|
gid = uint32(setGID & 0xFFFFFFFF) //#nosec G115 - masked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mode := uint32(st.Mode & 0o7777)
|
||||||
|
|
||||||
|
// Use portable helper to gather ctime
|
||||||
|
var cts int64
|
||||||
|
var ctns int32
|
||||||
|
if ft, err := goutilslib.LoadFileTime(path); err == nil {
|
||||||
|
cts = ft.Changed.Unix()
|
||||||
|
ctns = clampToInt32(ft.Changed.Nanosecond())
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildKGExtra(uid, gid, mode, cts, ctns)
|
||||||
|
}
|
||||||
|
|
||||||
// parseKGExtra scans a gzip Extra blob and returns kgz metadata if present.
|
// parseKGExtra scans a gzip Extra blob and returns kgz metadata if present.
|
||||||
func parseKGExtra(extra []byte) (uid, gid, mode uint32, ctimeS int64, ctimeNs int32, ok bool) {
|
func parseKGExtra(extra []byte) (uint32, uint32, uint32, int64, int32, bool) {
|
||||||
i := 0
|
i := 0
|
||||||
for i+4 <= len(extra) {
|
for i+4 <= len(extra) {
|
||||||
id1 := extra[i]
|
id1 := extra[i]
|
||||||
@@ -95,7 +142,16 @@ func parseKGExtra(extra []byte) (uid, gid, mode uint32, ctimeS int64, ctimeNs in
|
|||||||
if s.Version != 1 {
|
if s.Version != 1 {
|
||||||
return 0, 0, 0, 0, 0, false
|
return 0, 0, 0, 0, 0, false
|
||||||
}
|
}
|
||||||
return uint32(s.UID), uint32(s.GID), uint32(s.Mode), s.CTimeSec, s.CTimeNSec, true
|
// Validate ranges before converting from int -> uint32 to avoid overflow.
|
||||||
|
if s.UID < 0 || s.GID < 0 || s.Mode < 0 {
|
||||||
|
return 0, 0, 0, 0, 0, false
|
||||||
|
}
|
||||||
|
if uint64(s.UID) > math.MaxUint32 || uint64(s.GID) > math.MaxUint32 || uint64(s.Mode) > math.MaxUint32 {
|
||||||
|
return 0, 0, 0, 0, 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint32(s.UID & 0xFFFFFFFF), uint32(s.GID & 0xFFFFFFFF),
|
||||||
|
uint32(s.Mode & 0xFFFFFFFF), s.CTimeSec, s.CTimeNSec, true //#nosec G115 - masked
|
||||||
}
|
}
|
||||||
i += l
|
i += l
|
||||||
}
|
}
|
||||||
@@ -111,7 +167,7 @@ func compress(path, target string, level int, includeExtra bool, setUID, setGID
|
|||||||
|
|
||||||
// Gather file metadata
|
// Gather file metadata
|
||||||
var st unix.Stat_t
|
var st unix.Stat_t
|
||||||
if err := unix.Stat(path, &st); err != nil {
|
if err = unix.Stat(path, &st); err != nil {
|
||||||
return fmt.Errorf("stat source: %w", err)
|
return fmt.Errorf("stat source: %w", err)
|
||||||
}
|
}
|
||||||
fi, err := sourceFile.Stat()
|
fi, err := sourceFile.Stat()
|
||||||
@@ -132,23 +188,7 @@ func compress(path, target string, level int, includeExtra bool, setUID, setGID
|
|||||||
// Set header metadata
|
// Set header metadata
|
||||||
gzipCompressor.ModTime = fi.ModTime()
|
gzipCompressor.ModTime = fi.ModTime()
|
||||||
if includeExtra {
|
if includeExtra {
|
||||||
uid := uint32(st.Uid)
|
gzipCompressor.Extra = buildExtraForPath(st, path, setUID, setGID)
|
||||||
gid := uint32(st.Gid)
|
|
||||||
if setUID >= 0 {
|
|
||||||
uid = uint32(setUID)
|
|
||||||
}
|
|
||||||
if setGID >= 0 {
|
|
||||||
gid = uint32(setGID)
|
|
||||||
}
|
|
||||||
mode := uint32(st.Mode & 0o7777)
|
|
||||||
// Use portable helper to gather ctime
|
|
||||||
var cts int64
|
|
||||||
var ctns int32
|
|
||||||
if ft, err := goutilslib.LoadFileTime(path); err == nil {
|
|
||||||
cts = ft.Changed.Unix()
|
|
||||||
ctns = int32(ft.Changed.Nanosecond())
|
|
||||||
}
|
|
||||||
gzipCompressor.Extra = buildKGExtra(uid, gid, mode, cts, ctns)
|
|
||||||
}
|
}
|
||||||
defer gzipCompressor.Close()
|
defer gzipCompressor.Close()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user