mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-13 10:26:38 +08:00
refactor(backend): rename OpenFlare directory to lowercase openflare
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
// Copyright 2026 Arctel.net
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package pagesarchive
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Limits bounds archive inspection / extraction work.
|
||||
type Limits struct {
|
||||
// MaxFiles is the maximum number of regular files allowed.
|
||||
MaxFiles int
|
||||
// MaxFileBytes is the maximum size of a single extracted file.
|
||||
MaxFileBytes int64
|
||||
// MaxTotalBytes is the maximum sum of all extracted file sizes.
|
||||
MaxTotalBytes int64
|
||||
}
|
||||
|
||||
// FileEntry is a regular file discovered inside a deployment package.
|
||||
type FileEntry struct {
|
||||
Path string
|
||||
Size int64
|
||||
// Checksum is retained for API/schema compatibility and is left empty.
|
||||
// Integrity is enforced via the whole-package SHA-256 on the deployment record.
|
||||
Checksum string
|
||||
}
|
||||
|
||||
// Manifest is the inspected content of a Pages deployment package.
|
||||
type Manifest struct {
|
||||
Files []FileEntry
|
||||
FileCount int
|
||||
TotalSize int64
|
||||
}
|
||||
|
||||
// Entry describes one archive member for extraction.
|
||||
type Entry struct {
|
||||
// Name is the original path inside the archive.
|
||||
Name string
|
||||
// IsDir marks directory entries.
|
||||
IsDir bool
|
||||
// IsSymlink marks symbolic links (unsupported for Pages).
|
||||
IsSymlink bool
|
||||
// IsHardlink marks hard links (unsupported for Pages).
|
||||
IsHardlink bool
|
||||
// IsSpecial marks device, FIFO, socket, and other non-regular entries.
|
||||
IsSpecial bool
|
||||
// Size is the archive-declared uncompressed size; 0 means an empty member.
|
||||
Size uint64
|
||||
// Open returns a reader for the entry body. Caller must Close it.
|
||||
Open func() (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
// copyLimited copies actual bytes from src. maxBytes < 0 disables the byte cap;
|
||||
// maxBytes == 0 permits only an empty stream.
|
||||
func copyLimited(dst io.Writer, src io.Reader, maxBytes int64) (int64, error) {
|
||||
if maxBytes < 0 {
|
||||
return io.Copy(dst, src)
|
||||
}
|
||||
|
||||
readLimit := maxBytes
|
||||
if maxBytes < math.MaxInt64 {
|
||||
readLimit++
|
||||
}
|
||||
written, err := io.Copy(dst, io.LimitReader(src, readLimit))
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
if written > maxBytes {
|
||||
return written, errors.New("pages file size out of bounds")
|
||||
}
|
||||
return written, nil
|
||||
}
|
||||
|
||||
func copyAndVerifySize(dst io.Writer, src io.Reader, declaredSize uint64, maxBytes int64) (int64, error) {
|
||||
if declaredSize > uint64(math.MaxInt64) {
|
||||
return 0, errors.New("pages file size out of bounds")
|
||||
}
|
||||
written, err := copyLimited(dst, src, maxBytes)
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
//nolint:gosec // declaredSize is bounded to MaxInt64 above
|
||||
if written != int64(declaredSize) {
|
||||
return written, fmt.Errorf("pages declared size %d does not match actual %d", declaredSize, written)
|
||||
}
|
||||
return written, nil
|
||||
}
|
||||
|
||||
func writeEntryFile(targetPath string, src io.Reader, declaredSize uint64, maxBytes int64, perm os.FileMode) (int64, error) {
|
||||
if err := os.MkdirAll(filepath.Dir(targetPath), dirPerm); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
target, err := os.OpenFile(targetPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, perm) //nolint:gosec // caller validates path under release dir
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
written, copyErr := copyAndVerifySize(target, src, declaredSize, maxBytes)
|
||||
closeErr := target.Close()
|
||||
if err := errors.Join(copyErr, closeErr); err != nil {
|
||||
_ = os.Remove(targetPath)
|
||||
return written, err
|
||||
}
|
||||
return written, nil
|
||||
}
|
||||
Reference in New Issue
Block a user