blob: 502db25d92bbc923421b0a8facc83e683b66eb7f [file] [log] [blame]
Robin Thellend4523df62014-12-08 09:55:46 -08001package main
2
3import (
4 "errors"
5 "os"
6 "path/filepath"
7 "regexp"
8 "strconv"
9 "syscall"
10 "time"
11)
12
13var (
14 // The format of the log file names is:
15 // program.host.user.log.logger.tag.YYYYMMDD-HHmmss.pid
16 logFileRE = regexp.MustCompile(`^(.*)\.([^.]*)\.([^.]*)\.log\.([^.]*)\.([^.]*)\.(........-......)\.([0-9]*)$`)
17)
18
19type logFile struct {
20 // TODO(rthellend): Some of these fields are not used by anything yet,
21 // but they will be eventually when we need to sort the log files
22 // associated with a given instance.
23 symlink bool
24 program, host, user, logger, tag string
25 time time.Time
26 pid int
27}
28
29func parseFileInfo(dir string, fileInfo os.FileInfo) (*logFile, error) {
30 fileName := fileInfo.Name()
31 if fileInfo.Mode()&os.ModeSymlink != 0 {
32 buf := make([]byte, syscall.NAME_MAX)
33 n, err := syscall.Readlink(filepath.Join(dir, fileName), buf)
34 if err != nil {
35 return nil, err
36 }
37 linkName := string(buf[:n])
38 lf, err := parseFileName(linkName)
39 if err != nil {
40 return nil, err
41 }
42 lf.symlink = true
43 return lf, nil
44 }
45 return parseFileName(fileName)
46}
47
48func parseFileName(fileName string) (*logFile, error) {
49 if m := logFileRE.FindStringSubmatch(fileName); len(m) != 0 {
50 t, err := time.ParseInLocation("20060102-150405", m[6], time.Local)
51 if err != nil {
52 return nil, err
53 }
54 pid, err := strconv.ParseInt(m[7], 10, 32)
55 if err != nil {
56 return nil, err
57 }
58 return &logFile{
59 program: m[1],
60 host: m[2],
61 user: m[3],
62 logger: m[4],
63 tag: m[5],
64 time: t,
65 pid: int(pid),
66 }, nil
67 }
68 return nil, errors.New("not a recognized log file name")
69}