1515package logging
1616
1717import (
18+ "encoding/json"
1819 "fmt"
1920 "io"
2021 "math"
@@ -33,6 +34,43 @@ func init() {
3334 caddy .RegisterModule (FileWriter {})
3435}
3536
37+ // FileMode is a string made of 1 to 4 octal digits representing
38+ // a numeric mode as specified with the `chmod` unix command.
39+ // `"0777"` and `"777"` are thus equivalent values.
40+ type FileMode os.FileMode
41+
42+ // UnmarshalJSON satisfies json.Unmarshaler.
43+ func (m * FileMode ) UnmarshalJSON (b []byte ) error {
44+ if len (b ) == 0 {
45+ return io .EOF
46+ }
47+
48+ var s string
49+ if err := json .Unmarshal (b , & s ); err != nil {
50+ return err
51+ }
52+
53+ mode , err := ParseFileMode (s )
54+ if err != nil {
55+ return err
56+ }
57+
58+ * m = FileMode (mode )
59+ return err
60+ }
61+
62+ // ParseFileMode parses a file mode string,
63+ // adding support for `chmod` unix command like
64+ // 1 to 4 digital octal values.
65+ func ParseFileMode (s string ) (os.FileMode , error ) {
66+ modeStr := fmt .Sprintf ("%04s" , s )
67+ mode , err := strconv .ParseUint (modeStr , 8 , 32 )
68+ if err != nil {
69+ return 0 , err
70+ }
71+ return os .FileMode (mode ), nil
72+ }
73+
3674// FileWriter can write logs to files. By default, log files
3775// are rotated ("rolled") when they get large, and old log
3876// files get deleted, to ensure that the process does not
@@ -41,6 +79,10 @@ type FileWriter struct {
4179 // Filename is the name of the file to write.
4280 Filename string `json:"filename,omitempty"`
4381
82+ // The file permissions mode.
83+ // 0600 by default.
84+ Mode FileMode `json:"mode,omitempty"`
85+
4486 // Roll toggles log rolling or rotation, which is
4587 // enabled by default.
4688 Roll * bool `json:"roll,omitempty"`
@@ -100,6 +142,10 @@ func (fw FileWriter) WriterKey() string {
100142
101143// OpenWriter opens a new file writer.
102144func (fw FileWriter ) OpenWriter () (io.WriteCloser , error ) {
145+ if fw .Mode == 0 {
146+ fw .Mode = 0o600
147+ }
148+
103149 // roll log files by default
104150 if fw .Roll == nil || * fw .Roll {
105151 if fw .RollSizeMB == 0 {
@@ -116,6 +162,9 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
116162 fw .RollKeepDays = 90
117163 }
118164
165+ f_tmp , _ := os .OpenFile (fw .Filename , os .O_WRONLY | os .O_APPEND | os .O_CREATE , os .FileMode (fw .Mode ))
166+ f_tmp .Close ()
167+
119168 return & lumberjack.Logger {
120169 Filename : fw .Filename ,
121170 MaxSize : fw .RollSizeMB ,
@@ -127,12 +176,13 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
127176 }
128177
129178 // otherwise just open a regular file
130- return os .OpenFile (fw .Filename , os .O_WRONLY | os .O_APPEND | os .O_CREATE , 0o666 )
179+ return os .OpenFile (fw .Filename , os .O_WRONLY | os .O_APPEND | os .O_CREATE , os . FileMode ( fw . Mode ) )
131180}
132181
133182// UnmarshalCaddyfile sets up the module from Caddyfile tokens. Syntax:
134183//
135184// file <filename> {
185+ // mode <mode>
136186// roll_disabled
137187// roll_size <size>
138188// roll_uncompressed
@@ -150,7 +200,7 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
150200// The roll_keep_for duration has day resolution.
151201// Fractional values are rounded up to the next whole number of days.
152202//
153- // If any of the roll_size, roll_keep, or roll_keep_for subdirectives are
203+ // If any of the mode, roll_size, roll_keep, or roll_keep_for subdirectives are
154204// omitted or set to a zero value, then Caddy's default value for that
155205// subdirective is used.
156206func (fw * FileWriter ) UnmarshalCaddyfile (d * caddyfile.Dispenser ) error {
@@ -165,6 +215,17 @@ func (fw *FileWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
165215
166216 for d .NextBlock (0 ) {
167217 switch d .Val () {
218+ case "mode" :
219+ var modeStr string
220+ if ! d .AllArgs (& modeStr ) {
221+ return d .ArgErr ()
222+ }
223+ mode , err := ParseFileMode (modeStr )
224+ if err != nil {
225+ return d .Errf ("parsing mode: %v" , err )
226+ }
227+ fw .Mode = FileMode (mode )
228+
168229 case "roll_disabled" :
169230 var f bool
170231 fw .Roll = & f
0 commit comments