mirror of
https://github.com/gocsaf/csaf.git
synced 2025-12-22 11:55:40 +01:00
Moved commonly use file operations to separate package.
This commit is contained in:
parent
9d0ed98a17
commit
2fb2dfda78
7 changed files with 151 additions and 127 deletions
|
|
@ -16,6 +16,7 @@ import (
|
||||||
|
|
||||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||||
"github.com/csaf-poc/csaf_distribution/csaf"
|
"github.com/csaf-poc/csaf_distribution/csaf"
|
||||||
|
"github.com/csaf-poc/csaf_distribution/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const dateFormat = time.RFC3339
|
const dateFormat = time.RFC3339
|
||||||
|
|
@ -256,7 +257,7 @@ func (c *controller) upload(r *http.Request) (interface{}, error) {
|
||||||
rolie.SortEntriesByUpdated()
|
rolie.SortEntriesByUpdated()
|
||||||
|
|
||||||
// Store the feed
|
// Store the feed
|
||||||
if err := saveToFile(feed, rolie); err != nil {
|
if err := util.WriteToFile(feed, rolie); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/csaf-poc/csaf_distribution/csaf"
|
"github.com/csaf-poc/csaf_distribution/csaf"
|
||||||
|
"github.com/csaf-poc/csaf_distribution/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ensureFolders(c *config) error {
|
func ensureFolders(c *config) error {
|
||||||
|
|
@ -52,7 +53,7 @@ func createFeedFolders(c *config, wellknown string) error {
|
||||||
if _, err := filepath.EvalSymlinks(tlpLink); err != nil {
|
if _, err := filepath.EvalSymlinks(tlpLink); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
tlpFolder := filepath.Join(c.Folder, string(t))
|
tlpFolder := filepath.Join(c.Folder, string(t))
|
||||||
if tlpFolder, err = mkUniqDir(tlpFolder); err != nil {
|
if tlpFolder, err = util.MakeUniqDir(tlpFolder); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = os.Symlink(tlpFolder, tlpLink); err != nil {
|
if err = os.Symlink(tlpFolder, tlpLink); err != nil {
|
||||||
|
|
@ -104,5 +105,5 @@ func createProviderMetadata(c *config, wellknownCSAF string) error {
|
||||||
keyID, fingerprint := key.GetHexKeyID(), key.GetFingerprint()
|
keyID, fingerprint := key.GetHexKeyID(), key.GetFingerprint()
|
||||||
pm.SetPGP(fingerprint, c.GetOpenPGPURL(keyID))
|
pm.SetPGP(fingerprint, c.GetOpenPGPURL(keyID))
|
||||||
|
|
||||||
return saveToFile(path, pm)
|
return util.WriteToFile(path, pm)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,102 +8,9 @@ import (
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func deepCopy(dst, src string) error {
|
|
||||||
|
|
||||||
stack := []string{dst, src}
|
|
||||||
|
|
||||||
for len(stack) > 0 {
|
|
||||||
src = stack[len(stack)-1]
|
|
||||||
dst = stack[len(stack)-2]
|
|
||||||
stack = stack[:len(stack)-2]
|
|
||||||
|
|
||||||
if err := func() error {
|
|
||||||
dir, err := os.Open(src)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer dir.Close()
|
|
||||||
|
|
||||||
// Use Readdir as we need no sorting.
|
|
||||||
files, err := dir.Readdir(-1)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, f := range files {
|
|
||||||
nsrc := filepath.Join(src, f.Name())
|
|
||||||
ndst := filepath.Join(dst, f.Name())
|
|
||||||
if f.IsDir() {
|
|
||||||
// Create new sub dir
|
|
||||||
if err := os.Mkdir(ndst, 0755); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
stack = append(stack, ndst, nsrc)
|
|
||||||
} else if f.Mode().IsRegular() {
|
|
||||||
// Create hard link.
|
|
||||||
if err := os.Link(nsrc, ndst); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func mkUniqFile(prefix string) (string, *os.File, error) {
|
|
||||||
var file *os.File
|
|
||||||
name, err := mkUniq(prefix, func(name string) error {
|
|
||||||
var err error
|
|
||||||
file, err = os.OpenFile(name, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
return name, file, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func mkUniqDir(prefix string) (string, error) {
|
|
||||||
return mkUniq(prefix, func(name string) error { return os.Mkdir(name, 0755) })
|
|
||||||
}
|
|
||||||
|
|
||||||
func mkUniq(prefix string, create func(string) error) (string, error) {
|
|
||||||
now := time.Now()
|
|
||||||
stamp := now.Format("-2006-01-02-150405")
|
|
||||||
name := prefix + stamp
|
|
||||||
err := create(name)
|
|
||||||
if err == nil {
|
|
||||||
return name, nil
|
|
||||||
}
|
|
||||||
if os.IsExist(err) {
|
|
||||||
rnd := rand.New(rand.NewSource(now.Unix()))
|
|
||||||
|
|
||||||
for i := 0; i < 10000; i++ {
|
|
||||||
nname := name + "-" + strconv.FormatUint(uint64(rnd.Uint32()&0xff_ffff), 16)
|
|
||||||
err := create(nname)
|
|
||||||
if err == nil {
|
|
||||||
return nname, nil
|
|
||||||
}
|
|
||||||
if os.IsExist(err) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return "", &os.PathError{Op: "mkuniq", Path: name, Err: os.ErrExist}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeHash(fname, name string, h hash.Hash, data []byte) error {
|
func writeHash(fname, name string, h hash.Hash, data []byte) error {
|
||||||
|
|
||||||
if _, err := io.Copy(h, bytes.NewReader(data)); err != nil {
|
if _, err := io.Copy(h, bytes.NewReader(data)); err != nil {
|
||||||
|
|
@ -137,16 +44,3 @@ func writeHashedFile(fname, name string, data []byte, armored string) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveToFile(fname string, wt io.WriterTo) error {
|
|
||||||
f, err1 := os.Create(fname)
|
|
||||||
if err1 != nil {
|
|
||||||
return err1
|
|
||||||
}
|
|
||||||
_, err1 = wt.WriteTo(f)
|
|
||||||
err2 := f.Close()
|
|
||||||
if err1 != nil {
|
|
||||||
return err1
|
|
||||||
}
|
|
||||||
return err2
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/csaf-poc/csaf_distribution/csaf"
|
"github.com/csaf-poc/csaf_distribution/csaf"
|
||||||
|
"github.com/csaf-poc/csaf_distribution/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func doTransaction(
|
func doTransaction(
|
||||||
|
|
@ -42,13 +43,13 @@ func doTransaction(
|
||||||
|
|
||||||
folderTLP := filepath.Join(cfg.Folder, string(t))
|
folderTLP := filepath.Join(cfg.Folder, string(t))
|
||||||
|
|
||||||
newDir, err := mkUniqDir(folderTLP)
|
newDir, err := util.MakeUniqDir(folderTLP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy old content into new.
|
// Copy old content into new.
|
||||||
if err := deepCopy(newDir, oldDir); err != nil {
|
if err := util.DeepCopy(newDir, oldDir); err != nil {
|
||||||
os.RemoveAll(newDir)
|
os.RemoveAll(newDir)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +62,7 @@ func doTransaction(
|
||||||
|
|
||||||
// Write back provider metadata if its dynamic.
|
// Write back provider metadata if its dynamic.
|
||||||
if cfg.DynamicProviderMetaData {
|
if cfg.DynamicProviderMetaData {
|
||||||
newMetaName, newMetaFile, err := mkUniqFile(metadata)
|
newMetaName, newMetaFile, err := util.MakeUniqFile(metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.RemoveAll(newDir)
|
os.RemoveAll(newDir)
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/csaf-poc/csaf_distribution/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TLPLabel is the traffic light policy of the CSAF.
|
// TLPLabel is the traffic light policy of the CSAF.
|
||||||
|
|
@ -447,24 +449,13 @@ func NewProviderMetadataDomain(domain string, tlps []TLPLabel) *ProviderMetadata
|
||||||
return pm
|
return pm
|
||||||
}
|
}
|
||||||
|
|
||||||
type nWriter struct {
|
|
||||||
io.Writer
|
|
||||||
n int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (nw *nWriter) Write(p []byte) (int, error) {
|
|
||||||
n, err := nw.Writer.Write(p)
|
|
||||||
nw.n += int64(n)
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteTo saves a metadata provider to a writer.
|
// WriteTo saves a metadata provider to a writer.
|
||||||
func (pmd *ProviderMetadata) WriteTo(w io.Writer) (int64, error) {
|
func (pmd *ProviderMetadata) WriteTo(w io.Writer) (int64, error) {
|
||||||
nw := nWriter{w, 0}
|
nw := util.NWriter{w, 0}
|
||||||
enc := json.NewEncoder(&nw)
|
enc := json.NewEncoder(&nw)
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
err := enc.Encode(pmd)
|
err := enc.Encode(pmd)
|
||||||
return nw.n, err
|
return nw.N, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadProviderMetadata loads a metadata provider from a reader.
|
// LoadProviderMetadata loads a metadata provider from a reader.
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/csaf-poc/csaf_distribution/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Link for ROLIE.
|
// Link for ROLIE.
|
||||||
|
|
@ -70,11 +72,11 @@ func LoadROLIEFeed(r io.Reader) (*ROLIEFeed, error) {
|
||||||
|
|
||||||
// WriteTo saves a ROLIE feed to a writer.
|
// WriteTo saves a ROLIE feed to a writer.
|
||||||
func (rf *ROLIEFeed) WriteTo(w io.Writer) (int64, error) {
|
func (rf *ROLIEFeed) WriteTo(w io.Writer) (int64, error) {
|
||||||
nw := nWriter{w, 0}
|
nw := util.NWriter{w, 0}
|
||||||
enc := json.NewEncoder(&nw)
|
enc := json.NewEncoder(&nw)
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
err := enc.Encode(rf)
|
err := enc.Encode(rf)
|
||||||
return nw.n, err
|
return nw.N, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// EntryByID looks up an entry by its ID.
|
// EntryByID looks up an entry by its ID.
|
||||||
|
|
|
||||||
134
util/file.go
Normal file
134
util/file.go
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NWriter is an io.Writer counting the bytes copied through it.
|
||||||
|
type NWriter struct {
|
||||||
|
io.Writer
|
||||||
|
N int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write implements the Write method of io.Writer.
|
||||||
|
func (nw *NWriter) Write(p []byte) (int, error) {
|
||||||
|
n, err := nw.Writer.Write(p)
|
||||||
|
nw.N += int64(n)
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteToFile saves the content of wt into a file names fname.
|
||||||
|
func WriteToFile(fname string, wt io.WriterTo) error {
|
||||||
|
f, err1 := os.Create(fname)
|
||||||
|
if err1 != nil {
|
||||||
|
return err1
|
||||||
|
}
|
||||||
|
_, err1 = wt.WriteTo(f)
|
||||||
|
err2 := f.Close()
|
||||||
|
if err1 != nil {
|
||||||
|
return err1
|
||||||
|
}
|
||||||
|
return err2
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy copy a directory tree src to tree dst. Files are hard linked.
|
||||||
|
func DeepCopy(dst, src string) error {
|
||||||
|
|
||||||
|
stack := []string{dst, src}
|
||||||
|
|
||||||
|
for len(stack) > 0 {
|
||||||
|
src = stack[len(stack)-1]
|
||||||
|
dst = stack[len(stack)-2]
|
||||||
|
stack = stack[:len(stack)-2]
|
||||||
|
|
||||||
|
if err := func() error {
|
||||||
|
dir, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer dir.Close()
|
||||||
|
|
||||||
|
// Use Readdir as we need no sorting.
|
||||||
|
files, err := dir.Readdir(-1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range files {
|
||||||
|
nsrc := filepath.Join(src, f.Name())
|
||||||
|
ndst := filepath.Join(dst, f.Name())
|
||||||
|
if f.IsDir() {
|
||||||
|
// Create new sub dir
|
||||||
|
if err := os.Mkdir(ndst, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stack = append(stack, ndst, nsrc)
|
||||||
|
} else if f.Mode().IsRegular() {
|
||||||
|
// Create hard link.
|
||||||
|
if err := os.Link(nsrc, ndst); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeUniqFile creates a unique named file with the given prefix
|
||||||
|
// opened in write only mode.
|
||||||
|
// In case of name collisions the current date plus a random
|
||||||
|
// number is appended.
|
||||||
|
func MakeUniqFile(prefix string) (string, *os.File, error) {
|
||||||
|
var file *os.File
|
||||||
|
name, err := mkUniq(prefix, func(name string) error {
|
||||||
|
var err error
|
||||||
|
file, err = os.OpenFile(name, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
return name, file, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeUniqDir creates a unique named directory with the given prefix.
|
||||||
|
// In case of name collisions the current date plus a random
|
||||||
|
// number is appended.
|
||||||
|
func MakeUniqDir(prefix string) (string, error) {
|
||||||
|
return mkUniq(prefix, func(name string) error { return os.Mkdir(name, 0755) })
|
||||||
|
}
|
||||||
|
|
||||||
|
func mkUniq(prefix string, create func(string) error) (string, error) {
|
||||||
|
now := time.Now()
|
||||||
|
stamp := now.Format("-2006-01-02-150405")
|
||||||
|
name := prefix + stamp
|
||||||
|
err := create(name)
|
||||||
|
if err == nil {
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
if os.IsExist(err) {
|
||||||
|
rnd := rand.New(rand.NewSource(now.Unix()))
|
||||||
|
|
||||||
|
for i := 0; i < 10000; i++ {
|
||||||
|
nname := name + "-" + strconv.FormatUint(uint64(rnd.Uint32()&0xff_ffff), 16)
|
||||||
|
err := create(nname)
|
||||||
|
if err == nil {
|
||||||
|
return nname, nil
|
||||||
|
}
|
||||||
|
if os.IsExist(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return "", &os.PathError{Op: "mkuniq", Path: name, Err: os.ErrExist}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue