blob: ed18f48cb3317d56e4f1a3200e8e05d0b056f46f [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"errors"
"os"
"path/filepath"
"regexp"
"strconv"
"syscall"
"time"
)
var (
// The format of the log file names is:
// program.host.user.log.logger.tag.YYYYMMDD-HHmmss.pid
logFileRE = regexp.MustCompile(`^(.*)\.([^.]*)\.([^.]*)\.log\.([^.]*)\.([^.]*)\.(........-......)\.([0-9]*)$`)
)
type logFile struct {
// TODO(rthellend): Some of these fields are not used by anything yet,
// but they will be eventually when we need to sort the log files
// associated with a given instance.
symlink bool
program, host, user, logger, tag string
time time.Time
pid int
}
func parseFileInfo(dir string, fileInfo os.FileInfo) (*logFile, error) {
fileName := fileInfo.Name()
if fileInfo.Mode()&os.ModeSymlink != 0 {
buf := make([]byte, syscall.NAME_MAX)
n, err := syscall.Readlink(filepath.Join(dir, fileName), buf)
if err != nil {
return nil, err
}
linkName := string(buf[:n])
lf, err := parseFileName(linkName)
if err != nil {
return nil, err
}
lf.symlink = true
return lf, nil
}
return parseFileName(fileName)
}
func parseFileName(fileName string) (*logFile, error) {
if m := logFileRE.FindStringSubmatch(fileName); len(m) != 0 {
t, err := time.ParseInLocation("20060102-150405", m[6], time.Local)
if err != nil {
return nil, err
}
pid, err := strconv.ParseInt(m[7], 10, 32)
if err != nil {
return nil, err
}
return &logFile{
program: m[1],
host: m[2],
user: m[3],
logger: m[4],
tag: m[5],
time: t,
pid: int(pid),
}, nil
}
return nil, errors.New("not a recognized log file name")
}