summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandomChars <random@chars.jp>2021-07-30 21:40:59 +0900
committerRandomChars <random@chars.jp>2021-07-30 21:40:59 +0900
commite4d7584a18b8961bcbf9bf77173079fd92b5c59e (patch)
tree4eafd9c3ced293bd399594cf997d5bf2081012be
parentff106a3d2df3bc88f984b22862dd7df1b224fb1b (diff)
new page implementation, cleaner crashesv0.7.0
-rw-r--r--config.go11
-rw-r--r--go.mod1
-rw-r--r--go.sum12
-rw-r--r--log.go4
-rw-r--r--restart.go6
-rw-r--r--restart_windows.go9
-rw-r--r--store/image.go74
-rw-r--r--store/page.go233
-rw-r--r--store/paths.go13
-rw-r--r--store/secret.go11
-rw-r--r--store/store.go66
-rw-r--r--store/tag.go34
-rw-r--r--store/user.go34
-rw-r--r--web.go15
14 files changed, 223 insertions, 300 deletions
diff --git a/config.go b/config.go
index 796a288..cbe36a1 100644
--- a/config.go
+++ b/config.go
@@ -4,7 +4,6 @@ import (
"github.com/fsnotify/fsnotify"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
- "os"
"random.chars.jp/git/image-board/store"
)
@@ -39,13 +38,11 @@ func configSetup() {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
err = viper.WriteConfigAs("server.toml")
if err != nil {
- log.Fatalf("Error while generating default configuration, %s", err)
- os.Exit(1)
+ log.Fatalf("Error generating default configuration, %s", err)
}
log.Warn("Generated default server.toml in current directory.")
} else {
- log.Fatalf("Error while loading configuration, %s", err)
- os.Exit(1)
+ log.Fatalf("Error loading configuration, %s", err)
}
}
@@ -86,8 +83,7 @@ func openStore() {
}
instance = store.New(path, single)
if instance == nil {
- log.Fatalf("Unable to initialize store.")
- os.Exit(1)
+ log.Fatalf("Error initializing store.")
}
log.Infof("Store opened on %s revision %v compat %v.", path, instance.Revision, instance.Compat)
info := instance.User(instance.InitialUser)
@@ -99,7 +95,6 @@ func openStore() {
} else {
if single {
log.Fatal("Instance has no initial user, single user mode unavailable.")
- os.Exit(1)
}
}
if single {
diff --git a/go.mod b/go.mod
index 96d115e..c8ca18e 100644
--- a/go.mod
+++ b/go.mod
@@ -9,4 +9,5 @@ require (
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/sirupsen/logrus v1.8.1
github.com/spf13/viper v1.7.1
+ github.com/syndtr/goleveldb v1.0.0
)
diff --git a/go.sum b/go.sum
index d1bda17..fc13737 100644
--- a/go.sum
+++ b/go.sum
@@ -77,6 +77,8 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
+github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -115,6 +117,7 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
@@ -165,6 +168,9 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
@@ -210,6 +216,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
+github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
@@ -256,6 +264,7 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -280,6 +289,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -353,9 +363,11 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/log.go b/log.go
index 137590e..47b27c4 100644
--- a/log.go
+++ b/log.go
@@ -4,7 +4,6 @@ import (
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
"go/types"
- "os"
)
type logger types.Nil
@@ -37,8 +36,7 @@ func setFormatter() {
func setLevel() {
level, err := log.ParseLevel(viper.GetStringMap("system")["loglevel"].(string))
if err != nil {
- log.Fatalf("Error while parsing log level, %s", err)
- os.Exit(1)
+ log.Fatalf("Error parsing log level, %s", err)
}
log.SetLevel(level)
}
diff --git a/restart.go b/restart.go
index 9066c16..8b2ec79 100644
--- a/restart.go
+++ b/restart.go
@@ -12,14 +12,12 @@ func restart() {
var err error
if _, err = os.Stat(executable); err != nil {
- log.Fatalf("Error while stat executable path, %s", err)
- os.Exit(1)
+ log.Fatalf("Error stat executable path, %s", err)
}
log.Infof("Re-executing %s...", executable)
err = syscall.Exec(executable, os.Args, os.Environ())
if err != nil {
- log.Fatalf("Error while re-executing, %s", err)
- os.Exit(1)
+ log.Fatalf("Error re-executing, %s", err)
}
}
diff --git a/restart_windows.go b/restart_windows.go
index 4e239dd..59239fb 100644
--- a/restart_windows.go
+++ b/restart_windows.go
@@ -7,14 +7,12 @@ import (
func restart() {
if _, err := os.Stat(executable); err != nil {
- log.Fatalf("Unable to get executable path, %s", err)
- os.Exit(1)
+ log.Fatalf("Error getting executable path, %s", err)
}
log.Infof("Program found at %s.", executable)
wd, err := os.Getwd()
if err != nil {
- log.Fatalf("Unable to get working directory, %s", err)
- os.Exit(1)
+ log.Fatalf("Error getting working directory, %s", err)
}
log.Infof("Current working directory is %s.", wd)
_, err = os.StartProcess(executable, []string{}, &os.ProcAttr{
@@ -24,7 +22,6 @@ func restart() {
Sys: nil,
})
if err != nil {
- log.Fatalf("Unable to create new process, %s", err)
- os.Exit(1)
+ log.Fatalf("Error creating new process, %s", err)
}
}
diff --git a/store/image.go b/store/image.go
index d1b7549..6ef019d 100644
--- a/store/image.go
+++ b/store/image.go
@@ -31,15 +31,13 @@ type Image struct {
func (s *Store) Images() []string {
var images []string
if entries, err := os.ReadDir(s.ImagesDir()); err != nil {
- log.Fatalf("Error while reading first level image directory, %s", err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading first level image directory, %s", err))
} else {
for _, entry := range entries {
if entry.IsDir() {
var subEntries []os.DirEntry
if subEntries, err = os.ReadDir(s.ImagesDir() + "/" + entry.Name()); err != nil {
- log.Fatalf("Error while reading second level image directory %s, %s", entry.Name(), err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading second level image directory %s, %s", entry.Name(), err))
} else {
for _, subEntry := range subEntries {
images = append(images, entry.Name()+subEntry.Name())
@@ -66,12 +64,10 @@ func (s *Store) Image(hash string) Image {
func (s *Store) ImageMetadataRead(path string) Image {
var metadata Image
if payload, err := os.ReadFile(path); err != nil {
- log.Fatalf("Error while reading image metadata %s, %s", path, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading image metadata %s, %s", path, err))
} else {
if err = json.Unmarshal(payload, &metadata); err != nil {
- log.Fatalf("Error while parsing image metadata %s, %s", path, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error parsing image metadata %s, %s", path, err))
}
}
return metadata
@@ -87,12 +83,10 @@ func (s *Store) ImageData(hash string, preview bool) (Image, []byte) {
defer s.getLock(hash).RUnlock()
var metadata Image
if payload, err := os.ReadFile(s.ImageMetadataPath(hash)); err != nil {
- log.Fatalf("Error while reading image %s metadata, %s", hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading image %s metadata, %s", hash, err))
} else {
if err = json.Unmarshal(payload, &metadata); err != nil {
- log.Fatalf("Error while parsing image %s metadata, %s", hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error parsing image %s metadata, %s", hash, err))
}
}
var path string
@@ -102,8 +96,7 @@ func (s *Store) ImageData(hash string, preview bool) (Image, []byte) {
path = s.ImagePreviewFilePath(hash)
}
if data, err := os.ReadFile(path); err != nil {
- log.Fatalf("Error while reading image %s file, %s", hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading image %s file, %s", hash, err))
} else {
return metadata, data
}
@@ -124,8 +117,7 @@ func (s *Store) ImageTags(flake string) []string {
func (s *Store) imageTags(flake string) []string {
var tags []string
if entries, err := os.ReadDir(s.ImageTagsPath(flake)); err != nil {
- log.Fatalf("Error while reading tags of image %s, %s", flake, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading tags of image %s, %s", flake, err))
} else {
for _, entry := range entries {
tags = append(tags, entry.Name())
@@ -158,7 +150,7 @@ func (s *Store) ImageAdd(data []byte, flake string) Image {
// Decode image and set format
var img image.Image
if i, format, err := image.Decode(bytes.NewReader(data)); err != nil {
- log.Warnf("Error while decoding upload %s, %s", info.Hash, err)
+ log.Warnf("Error decoding upload %s, %s", info.Hash, err)
return Image{}
} else {
img = resize.Thumbnail(256, 256, i, resize.Bilinear)
@@ -167,39 +159,32 @@ func (s *Store) ImageAdd(data []byte, flake string) Image {
// Create image directory and tags
if err := os.MkdirAll(s.ImageHashTagsPath(info.Hash), s.PermissionDir); err != nil {
- log.Fatalf("Error while creating image %s directory, %s", info.Hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error creating image %s directory, %s", info.Hash, err))
}
// Generate and save image metadata
if payload, err := json.Marshal(info); err != nil {
- log.Fatalf("Error while encoding metadata of image %s, %s", info.Hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error encoding metadata of image %s, %s", info.Hash, err))
} else {
if err = os.WriteFile(s.ImageMetadataPath(info.Hash), payload, s.PermissionFile); err != nil {
- log.Fatalf("Error while saving metadata of image %s, %s", info.Hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error saving metadata of image %s, %s", info.Hash, err))
}
}
// Save image
if err := os.WriteFile(s.ImageFilePath(info.Hash), data, s.PermissionFile); err != nil {
- log.Fatalf("Error while saving image %s, %s", info.Hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error saving image %s, %s", info.Hash, err))
}
// Save preview image
if preview, err := os.Create(s.ImagePreviewFilePath(info.Hash)); err != nil {
- log.Fatalf("Error while creating image %s preview, %s", info.Hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error creating image %s preview, %s", info.Hash, err))
} else {
if err = jpeg.Encode(preview, img, &jpeg.Options{Quality: 100}); err != nil {
- log.Fatalf("Error while saving image %s preview, %s", info.Hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error saving image %s preview, %s", info.Hash, err))
}
if err = preview.Close(); err != nil {
- log.Fatalf("Error while closing image %s preview, %s", info.Hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error closing image %s preview, %s", info.Hash, err))
}
}
@@ -233,12 +218,10 @@ func (s *Store) ImageSource(hash, source string) {
// Set source and save
info.Source = source
if payload, err := json.Marshal(info); err != nil {
- log.Fatalf("Error while encoding metadata of image %s while updating source, %s", hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error encoding metadata of image %s while updating source, %s", hash, err))
} else {
if err = os.WriteFile(s.ImageMetadataPath(hash), payload, s.PermissionFile); err != nil {
- log.Fatalf("Error while saving metadata of image %s while updating source, %s", hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error saving metadata of image %s while updating source, %s", hash, err))
}
}
log.Infof("Image hash %s source set to %s.", hash, source)
@@ -248,8 +231,7 @@ func (s *Store) ImageSource(hash, source string) {
func (s *Store) ImageSnowflakes() []string {
var snowflakes []string
if entries, err := os.ReadDir(s.ImagesSnowflakeDir()); err != nil {
- log.Fatalf("Error while reading snowflakes, %s", err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading snowflakes, %s", err))
} else {
for _, entry := range entries {
snowflakes = append(snowflakes, entry.Name())
@@ -264,8 +246,7 @@ func (s *Store) ImageSnowflakeHash(flake string) string {
return s.ImageMetadataRead(s.ImageSnowflakePath(flake) + "/" + infoJson).Hash
} else {
if path, err := os.ReadFile(s.ImageSnowflakePath(flake)); err != nil {
- log.Fatalf("Error while reading snowflake %s association file, %s", flake, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading snowflake %s association file, %s", flake, err))
} else {
return s.ImageMetadataRead(string(path) + "/" + infoJson).Hash
}
@@ -297,20 +278,17 @@ func (s *Store) ImageDestroy(hash string) {
// Remove snowflake
if err := os.Remove(s.ImageSnowflakePath(info.Snowflake)); err != nil {
- log.Fatalf("Error while destroying snowflake %s of image %s, %s", info.Snowflake, hash, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error destroying snowflake %s of image %s, %s", info.Snowflake, hash, err))
}
// Disassociate user
if err := os.Remove(s.UserImagesPath(info.User) + "/" + info.Snowflake); err != nil {
- log.Fatalf("Error while destroying association %s with user %s, %s.", info.Snowflake, info.User, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error destroying association %s with user %s, %s.", info.Snowflake, info.User, err))
}
// Remove data directory
if err := os.RemoveAll(s.ImagePath(hash)); err != nil {
- log.Fatalf("Error while destroying image %s, %s", hash, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error destroying image %s, %s", hash, err))
}
// Register remove counter
@@ -349,14 +327,12 @@ func (s *Store) ImageTagRemove(flake, tag string) {
func (s *Store) imageTagRemove(flake, tag string) {
if s.file(s.ImageTagsPath(flake) + "/" + tag) {
if err := os.Remove(s.ImageTagsPath(flake) + "/" + tag); err != nil {
- log.Fatalf("Error while unreferencing image %s from tag %s, %s", flake, tag, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error unreferencing image %s from tag %s, %s", flake, tag, err))
}
}
if s.file(s.TagPath(tag) + "/" + flake) {
if err := os.Remove(s.TagPath(tag) + "/" + flake); err != nil {
- log.Fatalf("Error while unreferencing tag %s from image %s, %s", tag, flake, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error unreferencing tag %s from image %s, %s", tag, flake, err))
}
}
s.PageRegisterRemove("tag_"+tag, flake)
diff --git a/store/page.go b/store/page.go
index f8f8263..f654174 100644
--- a/store/page.go
+++ b/store/page.go
@@ -1,83 +1,125 @@
package store
+import "C"
import (
- "encoding/json"
+ "encoding/binary"
+ "fmt"
log "github.com/sirupsen/logrus"
+ "github.com/syndtr/goleveldb/leveldb"
"os"
- "strconv"
)
const pageSize = 64
-const balanceThreshold = 16
-
-// pageCreateIfNotExist creates a page variant's base directory if it does not exist.
-func (s *Store) pageCreateIfNotExist(variant string) {
- if !s.dir(s.PagesDir(variant)) {
- if err := os.MkdirAll(s.PagesDir(variant), s.PermissionDir); err != nil {
- log.Fatalf("Error while crating page variant %s base directory, %s", variant, err)
- os.Exit(1)
+
+// pageDB returns leveldb of page variant and creates it as required.
+func (s *Store) pageDB(variant string) *leveldb.DB {
+ if s.pageldb[variant] != nil {
+ return s.pageldb[variant]
+ } else {
+ if db, err := leveldb.OpenFile(s.PageVariantPath(variant), nil); err != nil {
+ s.fatalClose(fmt.Sprintf("Error opening leveldb for page variant %s, %s", variant, err))
+ } else {
+ s.pageldb[variant] = db
+ if _, err = db.Get([]byte("\000"), nil); err != nil {
+ log.Infof("Page variant %s created.", variant)
+ s.pageSetTotalCount(variant, 0)
+ }
+ return db
}
}
+ return nil
}
-// pageWrite writes payload of a page.
-func (s *Store) pageWrite(variant string, entry int, content []string) {
- if payload, err := json.Marshal(content); err != nil {
- log.Fatalf("Error while generating page %v of variant %s, %s", entry, variant, err)
- os.Exit(1)
+// pageDBDestroy destroys leveldb of page variant.
+func (s *Store) pageDBDestroy(variant string) {
+ if err := s.pageDB(variant).Close(); err != nil {
+ s.fatalClose(fmt.Sprintf("Error closing leveldb for page variant %s, %s", variant, err))
} else {
- s.pageCreateIfNotExist(variant)
- if err = os.WriteFile(s.PagePath(variant, entry), payload, s.PermissionFile); err != nil {
- log.Fatalf("Error while saving page %v, %s", entry, err)
- os.Exit(1)
- }
+ delete(s.pageldb, variant)
+ }
+
+ if err := os.RemoveAll(s.PageVariantPath(variant)); err != nil {
+ s.fatalClose(fmt.Sprintf("Error destroying page variant %s, %s", variant, err))
}
-}
-// pageLockString returns lock identifier of a page.
-func (s *Store) pageLockString(variant string, entry int) string {
- return "page_" + variant + "_" + strconv.Itoa(entry)
+ log.Infof("Page variant %s destroyed.", variant)
}
-// PageTotal returns total amount of pages.
-func (s *Store) PageTotal(variant string) int {
- s.pageCreateIfNotExist(variant)
- if entries, err := os.ReadDir(s.PagesDir(variant)); err != nil {
- log.Fatalf("Error while reading pages of variant %s, %s", variant, err)
- os.Exit(1)
+// pageGetTotalCount gets total count of a page variant.
+func (s *Store) pageGetTotalCount(variant string) uint64 {
+ db := s.pageDB(variant)
+
+ if payload, err := db.Get([]byte("\000"), nil); err != nil {
+ s.fatalClose(fmt.Sprintf("Error getting page variant %s total count, %s", variant, err))
} else {
- return len(entries)
+ return binary.LittleEndian.Uint64(payload)
}
+
return 0
}
-// Page returns all entries in a page.
-func (s *Store) Page(variant string, entry int) []string {
- return s.page(variant, entry, true)
+// pageSetTotalCount sets total count of a page variant.
+func (s *Store) pageSetTotalCount(variant string, value uint64) {
+ db := s.pageDB(variant)
+
+ payload := make([]byte, 8)
+ binary.LittleEndian.PutUint64(payload, value)
+
+ if err := db.Put([]byte("\000"), payload, nil); err != nil {
+ s.fatalClose(fmt.Sprintf("Error setting page variant %s total count, %s", variant, err))
+ }
+}
+
+// pageAdvanceTotalCount advances total count of a page variant.
+func (s *Store) pageAdvanceTotalCount(variant string) {
+ s.pageSetTotalCount(variant, s.pageGetTotalCount(variant)+1)
+}
+
+// pageReduceTotalCount reduces total count of a page variant.
+func (s *Store) pageReduceTotalCount(variant string) {
+ s.pageSetTotalCount(variant, s.pageGetTotalCount(variant)-1)
}
-// page returns all entries in a page with optional locking.
-func (s *Store) page(variant string, entry int, lock bool) []string {
- if !s.file(s.PagePath(variant, entry)) {
+// PageTotal returns total amount of pages.
+func (s *Store) PageTotal(variant string) int {
+ return (int(s.pageGetTotalCount(variant)) / pageSize) + 1
+}
+
+// Page returns all entries in a page.
+func (s *Store) Page(variant string, entry int) []string {
+ if entry >= s.PageTotal(variant) {
return nil
}
- if lock {
- s.getLock(s.pageLockString(variant, entry)).RLock()
- defer s.getLock(s.pageLockString(variant, entry)).RUnlock()
- }
+ var page []string
+ start := entry*pageSize + 1
+ end := start + pageSize
+ begin := false
- var flakes []string
- if payload, err := os.ReadFile(s.PagePath(variant, entry)); err != nil {
- log.Fatalf("Error while reading page %v of variant %s, %s", entry, variant, err)
- os.Exit(1)
- } else {
- if err = json.Unmarshal(payload, &flakes); err != nil {
- log.Fatalf("Error while parsing page %v of variant %s, %s", entry, variant, err)
- os.Exit(1)
+ db := s.pageDB(variant)
+
+ iter := db.NewIterator(nil, nil)
+ i := 0
+ for iter.Next() {
+ if i == end {
+ break
+ }
+ if begin {
+ page = append(page, string(iter.Key()))
+ } else {
+ if i >= start {
+ begin = true
+ }
}
+ i++
}
- return flakes
+ iter.Release()
+ if err := iter.Error(); err != nil {
+ log.Warnf("Error iterating page variant %s entry %v, %s", variant, entry, err)
+ return nil
+ }
+
+ return page
}
// PageImages returns all images in a page.
@@ -103,89 +145,24 @@ func (s *Store) PageInsert(variant, flake string) {
return
}
- entry := s.PageTotal(variant) - 1
- s.getLock(s.pageLockString(variant, entry)).Lock()
- defer s.getLock(s.pageLockString(variant, entry)).Unlock()
- var page []string
- if entry == -1 || len(s.page(variant, entry, false)) == pageSize {
- entry++
- page = []string{}
- } else {
- page = s.page(variant, entry, false)
+ s.getLock("page_" + variant).Lock()
+ defer s.getLock("page_" + variant).Unlock()
+
+ db := s.pageDB(variant)
+ if err := db.Put([]byte(flake), []byte{}, nil); err != nil {
+ s.fatalClose(fmt.Sprintf("Error inserting image %s into page variant %s, %s", flake, variant, err))
}
- page = append(page, flake)
- s.pageWrite(variant, entry, page)
+ s.pageAdvanceTotalCount(variant)
}
// PageRegisterRemove registers an image remove.
func (s *Store) PageRegisterRemove(variant, flake string) {
- go func() {
- var target int
- var targetPayload []string
- for i := 0; i < s.PageTotal(variant); i++ {
- page := s.page(variant, i, true)
- ok := false
- for j, f := range page {
- if f == flake {
- ok = true
- page = append(page[:(j)], page[(j+1):]...)
- break
- }
- }
- if ok {
- s.getLock(s.pageLockString(variant, i)).Lock()
- s.pageWrite(variant, i, page)
- s.getLock(s.pageLockString(variant, i)).Unlock()
- target = i
- targetPayload = page
- log.Infof("Removed page %v variant %s item %s.", target, variant, flake)
- break
- }
- }
- if len(targetPayload) < pageSize-balanceThreshold && (target+1) < s.PageTotal(variant) {
- log.Infof("Page %v reached balancing threshold, initiating balance.", target)
- s.PageBalance(variant, target, targetPayload)
- }
- }()
-}
+ s.getLock("page_" + variant).Lock()
+ defer s.getLock("page_" + variant).Unlock()
-// PageBalance balances a page.
-func (s *Store) PageBalance(variant string, target int, payload []string) {
- if !s.file(s.PagePath(variant, target)) {
- return
+ db := s.pageDB(variant)
+ if err := db.Delete([]byte(flake), nil); err != nil {
+ s.fatalClose(fmt.Sprintf("Error removing image %s from page variant %s, %s", flake, variant, err))
}
- go func() {
- if (target + 1) >= s.PageTotal(variant) {
- return
- }
- s.getLock(s.pageLockString(variant, target)).Lock()
- defer s.getLock(s.pageLockString(variant, target)).Unlock()
- s.getLock(s.pageLockString(variant, target+1)).Lock()
- defer s.getLock(s.pageLockString(variant, target+1)).Unlock()
- if payload == nil {
- payload = s.page(variant, target, false)
- }
- comp := pageSize - len(payload)
- next := s.page(variant, target+1, false)
- empty := false
- if len(next) <= comp {
- if err := os.Remove(s.PagePath(variant, target+1)); err != nil {
- log.Fatalf("Error removing empty page %v, %s", target+1, err)
- os.Exit(1)
- }
- payload = append(payload, next...)
- empty = true
- } else {
- payload = append(payload, next[:comp]...)
- next = next[comp+1:]
- }
-
- s.pageWrite(variant, target, payload)
- if !empty {
- s.pageWrite(variant, target+1, next)
- s.PageBalance(variant, target+1, next)
- } else {
- log.Infof("Removed empty page %v.", target+1)
- }
- }()
+ s.pageReduceTotalCount(variant)
}
diff --git a/store/paths.go b/store/paths.go
index bd567cb..b31f3d8 100644
--- a/store/paths.go
+++ b/store/paths.go
@@ -1,9 +1,5 @@
package store
-import (
- "strconv"
-)
-
const infoJson = "info.json"
// LockPath returns path to lock file.
@@ -126,12 +122,7 @@ func (s *Store) PageBaseDir() string {
return s.Path + "/pages"
}
-// PagesDir returns path to pages of a variant.
-func (s *Store) PagesDir(variant string) string {
+// PageVariantPath returns path to pages of a variant.
+func (s *Store) PageVariantPath(variant string) string {
return s.PageBaseDir() + "/" + variant
}
-
-// PagePath returns path to a specific page.
-func (s *Store) PagePath(variant string, entry int) string {
- return s.PagesDir(variant) + "/" + strconv.Itoa(entry)
-}
diff --git a/store/secret.go b/store/secret.go
index c17443a..5941c2f 100644
--- a/store/secret.go
+++ b/store/secret.go
@@ -2,7 +2,7 @@ package store
import (
"crypto/rand"
- log "github.com/sirupsen/logrus"
+ "fmt"
"math/big"
"os"
)
@@ -12,8 +12,7 @@ func (s *Store) SecretNew() string {
secret := make([]byte, 64)
for i := 0; i < 64; i++ {
if n, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))); err != nil {
- log.Fatalf("Error while generating secret, %s", err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error generating secret, %s", err))
} else {
secret[i] = letters[n.Int64()]
}
@@ -30,8 +29,7 @@ func (s *Store) SecretLookup(secret string) User {
return s.user(s.SecretPath(secret) + "/" + infoJson)
} else {
if path, err := os.ReadFile(s.SecretPath(secret)); err != nil {
- log.Fatalf("Error reading association file of secret %s, %s", secret, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading association file of secret %s, %s", secret, err))
} else {
return s.user(string(path) + "/" + infoJson)
}
@@ -53,7 +51,6 @@ func (s *Store) SecretDisassociate(secret string) {
return
}
if err := os.Remove(s.SecretPath(secret)); err != nil {
- log.Fatalf("Error disassociating secret %s, %s", secret, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error disassociating secret %s, %s", secret, err))
}
}
diff --git a/store/store.go b/store/store.go
index f7420aa..619eff4 100644
--- a/store/store.go
+++ b/store/store.go
@@ -2,15 +2,17 @@ package store
import (
"encoding/json"
+ "fmt"
"github.com/bwmarrin/snowflake"
log "github.com/sirupsen/logrus"
+ "github.com/syndtr/goleveldb/leveldb"
"os"
"runtime"
"strconv"
"sync"
)
-const revision = -6
+const revision = -7
var (
imageNode *snowflake.Node
@@ -37,6 +39,7 @@ type Store struct {
InitialUser string
PermissionDir os.FileMode
PermissionFile os.FileMode
+ pageldb map[string]*leveldb.DB
mutex map[string]*sync.RWMutex
sync.RWMutex
}
@@ -50,8 +53,7 @@ func init() {
imageNode, err = snowflake.NewNode(9)
userNode, err = snowflake.NewNode(7)
if err != nil {
- log.Fatalf("Error while creating snowflake generation node, %s", err)
- os.Exit(1)
+ log.Fatalf("Error creating snowflake generation node, %s", err)
}
}
@@ -69,17 +71,16 @@ func New(path string, single bool) *Store {
Register: false,
PermissionDir: 0700,
PermissionFile: 0600,
+ pageldb: make(map[string]*leveldb.DB),
mutex: make(map[string]*sync.RWMutex),
}
if err = store.create(); err != nil {
log.Fatalf("Error creating store, %s", err)
- os.Exit(1)
}
} else {
// Exit if store is not a directory.
if !stat.IsDir() {
log.Fatal("Store is not a directory.")
- os.Exit(1)
}
// Load and parse store info.
@@ -87,16 +88,13 @@ func New(path string, single bool) *Store {
var payload []byte
if payload, err = os.ReadFile(path + "/" + infoJson); err != nil {
log.Fatalf("Error reading store information, %s", err)
- os.Exit(1)
} else {
if err = json.Unmarshal(payload, &info); err != nil {
log.Fatalf("Error parsing store information, %s", err)
- os.Exit(1)
}
}
if info.Revision != revision {
log.Fatalf("Store format revision %v, expecting revision %v.", info.Revision, revision)
- os.Exit(1)
}
// Create store instance.
@@ -109,34 +107,50 @@ func New(path string, single bool) *Store {
InitialUser: info.InitialUser,
PermissionDir: info.PermissionDir,
PermissionFile: info.PermissionFile,
+ pageldb: make(map[string]*leveldb.DB),
mutex: make(map[string]*sync.RWMutex),
}
}
+
+ // Handle store locking
if store.file(store.LockPath()) {
if pid, err := os.ReadFile(store.LockPath()); err != nil {
log.Fatalf("Store locked, lock file unreadable, %s", err)
- log.Exit(1)
} else {
log.Fatalf("Store locked by process %s.", string(pid))
- log.Exit(1)
}
}
if err := os.WriteFile(store.LockPath(), []byte(strconv.Itoa(os.Getpid())), store.PermissionFile); err != nil {
log.Fatalf("Error locking store, %s", err)
- log.Exit(1)
}
+
return store
}
// Close closes the store.
func (s *Store) Close() {
+ // Close all leveldb
+ for variant, ldb := range s.pageldb {
+ if err := ldb.Close(); err != nil {
+ log.Errorf("Error closing leveldb variant %s, %s", variant, err)
+ }
+ log.Infof("Page variant %s closed.", variant)
+ }
+
+ // Unlock store
if err := os.Remove(s.LockPath()); err != nil {
- log.Fatalf("Error unlocking store, %s", err)
- log.Exit(1)
+ log.Errorf("Error unlocking store, %s", err)
}
+
log.Info("Store closed.")
}
+// fatalClose closes the store and as cleanly as possible and exits with a fatal message.
+func (s *Store) fatalClose(message string) {
+ s.Close()
+ log.Fatal(message)
+}
+
// create sets up the store directory if it does not exist.
func (s *Store) create() error {
// Check if exists
@@ -163,18 +177,17 @@ func (s *Store) create() error {
if err := os.Mkdir(s.SecretsDir(), s.PermissionDir); err != nil {
return err
}
- if err := os.Mkdir(s.PageBaseDir(), s.PermissionDir); err != nil {
+ if err := os.Mkdir(s.UsernamesDir(), s.PermissionDir); err != nil {
return err
}
- if err := os.Mkdir(s.UsernamesDir(), s.PermissionDir); err != nil {
+ if err := os.Mkdir(s.PageBaseDir(), s.PermissionDir); err != nil {
return err
}
// Create initial user
info := s.UserAdd("root", true, "initial")
if info.Snowflake == "" {
- log.Fatalf("Error creating initial user.")
- os.Exit(1)
+ log.Fatal("Error creating initial user.")
} else {
log.Infof("Created initial user with username root and password initial.")
}
@@ -219,8 +232,7 @@ func (s *Store) file(path string) bool {
if os.IsNotExist(err) {
return false
} else {
- log.Fatalf("Error while stat %s, %s", path, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error stat %s, %s", path, err))
}
}
return true
@@ -232,13 +244,11 @@ func (s *Store) dir(path string) bool {
if os.IsNotExist(err) {
return false
} else {
- log.Fatalf("Error while stat %s, %s", path, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error stat %s, %s", path, err))
}
} else {
if !stat.IsDir() {
- log.Fatalf("Path %s is not a directory.", path)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Path %s is not a directory.", path))
}
}
return true
@@ -257,13 +267,11 @@ func (s *Store) flake(flake string) bool {
func (s *Store) link(old, new string) {
if !s.Compat {
if err := os.Symlink(old, new); err != nil {
- log.Fatalf("Error while linking %s to %s, %s", old, new, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error linking %s to %s, %s", old, new, err))
}
} else {
if err := os.WriteFile(new, []byte(old), s.PermissionFile); err != nil {
- log.Fatalf("Error while writing associate file for %s to %s, %s", old, new, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error writing associate file for %s to %s, %s", old, new, err))
}
}
}
@@ -276,7 +284,6 @@ func (s *Store) readlink(path string) string {
// return ""
// } else {
// log.Fatalf("Error reading symlink %s, %s.", path, err)
- // os.Exit(1)
// }
//} else {
// return final
@@ -287,8 +294,7 @@ func (s *Store) readlink(path string) string {
if os.IsNotExist(err) {
return ""
} else {
- log.Fatalf("Error reading association file %s, %s.", path, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading association file %s, %s.", path, err))
}
} else {
return string(final)
diff --git a/store/tag.go b/store/tag.go
index 5f717bd..2c11880 100644
--- a/store/tag.go
+++ b/store/tag.go
@@ -2,6 +2,7 @@ package store
import (
"encoding/json"
+ "fmt"
log "github.com/sirupsen/logrus"
"os"
"time"
@@ -17,8 +18,7 @@ type Tag struct {
func (s *Store) Tags() []string {
var tags []string
if entries, err := os.ReadDir(s.TagsDir()); err != nil {
- log.Fatalf("Error while reading tags, %s", err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading tags, %s", err))
} else {
for _, entry := range entries {
if entry.IsDir() {
@@ -36,8 +36,7 @@ func (s *Store) Tag(tag string) []string {
}
var images []string
if entries, err := os.ReadDir(s.TagPath(tag)); err != nil {
- log.Fatalf("Error while reading tag %s, %s", tag, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading tag %s, %s", tag, err))
} else {
for _, entry := range entries {
if entry.Name() == infoJson {
@@ -58,16 +57,13 @@ func (s *Store) TagCreate(tag string) bool {
return false
}
if err := os.Mkdir(s.TagPath(tag), s.PermissionDir); err != nil {
- log.Fatalf("Error while creating tag %s, %s", tag, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error creating tag %s, %s", tag, err))
}
if payload, err := json.Marshal(Tag{Type: Generic, CreationTime: time.Now().UTC()}); err != nil {
- log.Fatalf("Error while generating tag %s metadata, %s", tag, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error generating tag %s metadata, %s", tag, err))
} else {
if err = os.WriteFile(s.TagMetadataPath(tag), payload, s.PermissionFile); err != nil {
- log.Fatalf("Error while writing tag %s metadata, %s", tag, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error writing tag %s metadata, %s", tag, err))
}
}
log.Infof("Tag %s created.", tag)
@@ -87,12 +83,10 @@ func (s *Store) TagDestroy(tag string) {
s.ImageTagRemove(flake, tag)
}
if err := os.Remove(s.TagMetadataPath(tag)); err != nil {
- log.Fatalf("Error removing tag %s metadata, %s", tag, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error removing tag %s metadata, %s", tag, err))
}
if err := os.Remove(s.TagPath(tag)); err != nil {
- log.Fatalf("Error removing tag %s, %s", tag, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error removing tag %s, %s", tag, err))
}
log.Infof("Tag %s destroyed.", tag)
}
@@ -106,13 +100,11 @@ func (s *Store) TagInfo(tag string) Tag {
s.getLock("tag_" + tag).RLock()
defer s.getLock("tag_" + tag).RUnlock()
if payload, err := os.ReadFile(s.TagMetadataPath(tag)); err != nil {
- log.Fatalf("Error while reading tag %s metadata, %s", tag, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading tag %s metadata, %s", tag, err))
} else {
var info Tag
if err = json.Unmarshal(payload, &info); err != nil {
- log.Fatalf("Error while parsing tag %s metadata, %s", tag, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error parsing tag %s metadata, %s", tag, err))
} else {
return info
}
@@ -141,12 +133,10 @@ func (s *Store) TagType(tag, t string) {
info := s.TagInfo(tag)
info.Type = t
if payload, err := json.Marshal(info); err != nil {
- log.Fatalf("Error while updating tag %s metadata, %s", tag, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error updating tag %s metadata, %s", tag, err))
} else {
if err = os.WriteFile(s.TagMetadataPath(tag), payload, s.PermissionFile); err != nil {
- log.Fatalf("Error while writing tag %s metadata, %s", tag, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error writing tag %s metadata, %s", tag, err))
}
}
log.Infof("Tag %s type set to %s.", tag, t)
diff --git a/store/user.go b/store/user.go
index d6772c3..7f9eabd 100644
--- a/store/user.go
+++ b/store/user.go
@@ -2,6 +2,7 @@ package store
import (
"encoding/json"
+ "fmt"
log "github.com/sirupsen/logrus"
"os"
)
@@ -17,13 +18,11 @@ type User struct {
// user parses user metadata file.
func (s *Store) user(path string) User {
if payload, err := os.ReadFile(path); err != nil {
- log.Fatalf("Error while reading user metadata %s, %s", path, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading user metadata %s, %s", path, err))
} else {
var info User
if err = json.Unmarshal(payload, &info); err != nil {
- log.Fatalf("Error while parsing user metadata %s, %s", path, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error parsing user metadata %s, %s", path, err))
} else {
return info
}
@@ -46,8 +45,7 @@ func (s *Store) User(flake string) User {
func (s *Store) Users() []string {
var users []string
if entries, err := os.ReadDir(s.UsersDir()); err != nil {
- log.Fatalf("Error while reading users, %s", err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading users, %s", err))
} else {
for _, entry := range entries {
if entry.IsDir() {
@@ -61,12 +59,10 @@ func (s *Store) Users() []string {
// UserMetadata sets user metadata.
func (s *Store) UserMetadata(info User) {
if payload, err := json.Marshal(info); err != nil {
- log.Fatalf("Error while updating user %s metadata, %s", info.Snowflake, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error updating user %s metadata, %s", info.Snowflake, err))
} else {
if err = os.WriteFile(s.UserMetadataPath(info.Snowflake), payload, s.PermissionFile); err != nil {
- log.Fatalf("Error while writing user %s metadata, %s", info.Snowflake, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error writing user %s metadata, %s", info.Snowflake, err))
}
}
}
@@ -85,8 +81,7 @@ func (s *Store) UserAdd(username string, privileged bool, password string) User
}
// Create user directory and images
if err := os.MkdirAll(s.UserImagesPath(info.Snowflake), s.PermissionDir); err != nil {
- log.Fatalf("Error while creating user %s directory, %s", info.Snowflake, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error creating user %s directory, %s", info.Snowflake, err))
}
s.getLock(info.Snowflake).Lock()
defer s.getLock(info.Snowflake).Unlock()
@@ -196,8 +191,7 @@ func (s *Store) userUsernameAssociate(flake, username string) {
// userUsernameDisassociate disassociates specific username.
func (s *Store) userUsernameDisassociate(username string) {
if err := os.Remove(s.UsernamePath(username)); err != nil {
- log.Fatalf("Error disassociating username %s, %s", username, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error disassociating username %s, %s", username, err))
}
}
@@ -207,8 +201,7 @@ func (s *Store) userPassword(path string) string {
if os.IsNotExist(err) {
return ""
}
- log.Fatalf("Error reading password from user directory %s, %s", path, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading password from user directory %s, %s", path, err))
} else {
return string(payload)
}
@@ -221,8 +214,7 @@ func (s *Store) userPasswordUpdate(path, password string) bool {
return false
}
if err := os.WriteFile(path+"/passwd", []byte(password), s.PermissionFile); err != nil {
- log.Fatalf("Error setting password for user directory %s, %s", path, err)
- log.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error setting password for user directory %s, %s", path, err))
} else {
return true
}
@@ -295,8 +287,7 @@ func (s *Store) UserDestroy(flake string) {
s.SecretDisassociate(info.Snowflake)
// Remove user data directory
if err := os.RemoveAll(s.UserPath(flake)); err != nil {
- log.Fatalf("Error destroying user %s data directory, %s", flake, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error destroying user %s data directory, %s", flake, err))
}
log.Infof("User %s username %s destroyed.", info.Snowflake, info.Username)
}
@@ -312,8 +303,7 @@ func (s *Store) UserImages(flake string) []string {
var images []string
if entries, err := os.ReadDir(s.UserImagesPath(flake)); err != nil {
- log.Fatalf("Error while reading user %s images, %s", flake, err)
- os.Exit(1)
+ s.fatalClose(fmt.Sprintf("Error reading user %s images, %s", flake, err))
} else {
for _, entry := range entries {
images = append(images, entry.Name())
diff --git a/web.go b/web.go
index 6456ca4..9f754a2 100644
--- a/web.go
+++ b/web.go
@@ -57,22 +57,19 @@ func listenerSetup() {
strconv.Itoa(int(serverConfig["port"].(int64))))
listener, err = net.Listen("tcp", address)
if err != nil {
- log.Errorf("Unable to listen on %s, %s", address, err)
- os.Exit(1)
+ log.Errorf("Error binding %s, %s", address, err)
}
log.Infof("Web server listening on %s.", address)
case true:
path := serverConfig["host"].(string)
listener, err = net.Listen("unix", path)
if err != nil {
- log.Errorf("Unable to listen on %s, %s", path, err)
- os.Exit(1)
+ log.Errorf("Error binding %s, %s", path, err)
}
err = syscall.Chmod(path, 0777)
if err != nil {
- log.Errorf("Unable to change permission of web server socket, %s", err)
- os.Exit(1)
+ log.Errorf("Error changing permission of web server socket, %s", err)
}
log.Infof("Web server listening on unix socket %s.", path)
@@ -87,8 +84,7 @@ func runWebServer() {
if err == http.ErrServerClosed {
log.Info("Web server closed.")
} else {
- log.Errorf("Error while serving, %s", err)
- os.Exit(1)
+ log.Errorf("Error starting server, %s", err)
}
}
@@ -105,8 +101,7 @@ func registerWebpage() {
var public fs.FS
public, err = fs.Sub(assets, "assets")
if err != nil {
- log.Fatalf("Error while getting subdirectory, %s", err)
- os.Exit(1)
+ log.Fatalf("Error getting subdirectory, %s", err)
}
router.StaticFS("/web", http.FS(public))
}