Skip to content

Commit

Permalink
allows for mode with 1 to 4 digital octal values
Browse files Browse the repository at this point in the history
Allows for chmod compatible octal values specification in configuration.
  • Loading branch information
ririsoft committed May 15, 2024
1 parent e8cc8f2 commit cc499d0
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 8 deletions.
48 changes: 43 additions & 5 deletions modules/logging/filewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package logging

import (
"encoding/json"
"fmt"
"io"
"math"
Expand All @@ -33,6 +34,43 @@ func init() {
caddy.RegisterModule(FileWriter{})
}

// FileMode is a string made of 1 to 4 octal digits representing
// a numeric mode as specified with the `chmod` unix command.
// `"0777"` and `"777"` are thus equivalent values.
type FileMode os.FileMode

// UnmarshalJSON satisfies json.Unmarshaler.
func (m *FileMode) UnmarshalJSON(b []byte) error {
if len(b) == 0 {
return io.EOF
}

var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}

mode, err := ParseFileMode(s)
if err != nil {
return err
}

*m = FileMode(mode)
return err
}

// ParseFileMode parses a file mode string,
// adding support for `chmod` unix command like
// 1 to 4 digital octal values.
func ParseFileMode(s string) (os.FileMode, error) {
modeStr := fmt.Sprintf("%04s", s)
mode, err := strconv.ParseUint(modeStr, 8, 32)
if err != nil {
return 0, err
}
return os.FileMode(mode), nil
}

// FileWriter can write logs to files. By default, log files
// are rotated ("rolled") when they get large, and old log
// files get deleted, to ensure that the process does not
Expand All @@ -43,7 +81,7 @@ type FileWriter struct {

// The file permissions mode.
// 0600 by default.
Mode os.FileMode `json:"mode,omitempty"`
Mode FileMode `json:"mode,omitempty"`

// Roll toggles log rolling or rotation, which is
// enabled by default.
Expand Down Expand Up @@ -124,7 +162,7 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
fw.RollKeepDays = 90
}

f_tmp, _ := os.OpenFile(fw.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, fw.Mode)
f_tmp, _ := os.OpenFile(fw.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(fw.Mode))
f_tmp.Close()

return &lumberjack.Logger{
Expand All @@ -138,7 +176,7 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
}

// otherwise just open a regular file
return os.OpenFile(fw.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, fw.Mode)
return os.OpenFile(fw.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(fw.Mode))
}

// UnmarshalCaddyfile sets up the module from Caddyfile tokens. Syntax:
Expand Down Expand Up @@ -182,11 +220,11 @@ func (fw *FileWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if !d.AllArgs(&modeStr) {
return d.ArgErr()
}
mode, err := strconv.ParseUint(modeStr, 0, 32)
mode, err := ParseFileMode(modeStr)
if err != nil {
return d.Errf("parsing mode: %v", err)
}
fw.Mode = os.FileMode(mode)
fw.Mode = FileMode(mode)

case "roll_disabled":
var f bool
Expand Down
97 changes: 94 additions & 3 deletions modules/logging/filewriter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package logging

import (
"encoding/json"
"os"
"path"
"testing"
Expand Down Expand Up @@ -107,7 +108,7 @@ func TestFileRotationPreserveMode(t *testing.T) {
fpath := path.Join(dir, "test.log")

roll := true
mode := os.FileMode(0o640)
mode := FileMode(0o640)
fw := FileWriter{
Filename: fpath,
Mode: mode,
Expand Down Expand Up @@ -144,7 +145,7 @@ func TestFileRotationPreserveMode(t *testing.T) {
t.Fatalf("failed to check file permissions: %v", err)
}

if st.Mode() != mode {
if st.Mode() != os.FileMode(mode) {
t.Errorf("file mode is %v, want %v", st.Mode(), mode)
}

Expand All @@ -157,7 +158,7 @@ func TestFileRotationPreserveMode(t *testing.T) {
t.Fatalf("failed to check file permissions: %v", err)
}

if st.Mode() != mode {
if st.Mode() != os.FileMode(mode) {
t.Errorf("file mode is %v, want %v", st.Mode(), mode)
}
}
Expand All @@ -181,6 +182,42 @@ file test.log {
},
wantErr: false,
},
{
name: "set mode 3 digits",
d: caddyfile.NewTestDispenser(`
file test.log {
mode 666
}
`),
fw: FileWriter{
Mode: 0o666,
},
wantErr: false,
},
{
name: "set mode 2 digits",
d: caddyfile.NewTestDispenser(`
file test.log {
mode 66
}
`),
fw: FileWriter{
Mode: 0o066,
},
wantErr: false,
},
{
name: "set mode 1 digits",
d: caddyfile.NewTestDispenser(`
file test.log {
mode 6
}
`),
fw: FileWriter{
Mode: 0o006,
},
wantErr: false,
},
{
name: "invalid mode",
d: caddyfile.NewTestDispenser(`
Expand All @@ -205,3 +242,57 @@ file test.log {
})
}
}

func TestFileModeJSON(t *testing.T) {
tests := []struct {
name string
config string
fw FileWriter
wantErr bool
}{
{
name: "set mode",
config: `
{
"mode": "0666"
}
`,
fw: FileWriter{
Mode: 0o666,
},
wantErr: false,
},
{
name: "set mode invalid value",
config: `
{
"mode": "0x666"
}
`,
fw: FileWriter{},
wantErr: true,
},
{
name: "set mode invalid string",
config: `
{
"mode": 777
}
`,
fw: FileWriter{},
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fw := &FileWriter{}
if err := json.Unmarshal([]byte(tt.config), fw); (err != nil) != tt.wantErr {
t.Fatalf("UnmarshalJSON() error = %v, want %v", err, tt.wantErr)
}
if fw.Mode != tt.fw.Mode {
t.Errorf("got mode %v, want %v", fw.Mode, tt.fw.Mode)
}
})
}
}

0 comments on commit cc499d0

Please sign in to comment.