func (j *Journal) GetEntry() (*JournalEntry, error) {
	sd_journal_get_realtime_usec, err := getFunction("sd_journal_get_realtime_usec")
	if err != nil {
		return nil, err
	}
	sd_journal_get_monotonic_usec, err := getFunction("sd_journal_get_monotonic_usec")
	if err != nil {
		return nil, err
	}
	sd_journal_get_cursor, err := getFunction("sd_journal_get_cursor")
	if err != nil {
		return nil, err
	}
	sd_journal_restart_data, err := getFunction("sd_journal_restart_data")
	if err != nil {
		return nil, err
	}
	sd_journal_enumerate_data, err := getFunction("sd_journal_enumerate_data")
	if err != nil {
		return nil, err
	}
	j.mu.Lock()
	defer j.mu.Unlock()
	var r C.int
	entry := &JournalEntry{Fields: make(map[string]string)}
	var realtimeUsec C.uint64_t
	r = C.my_sd_journal_get_realtime_usec(sd_journal_get_realtime_usec, j.cjournal, &realtimeUsec)
	if r < 0 {
		return nil, fmt.Errorf("failed to get realtime timestamp: %d", syscall.Errno(-r))
	}
	entry.RealtimeTimestamp = uint64(realtimeUsec)
	var monotonicUsec C.uint64_t
	var boot_id C.sd_id128_t
	r = C.my_sd_journal_get_monotonic_usec(sd_journal_get_monotonic_usec, j.cjournal, &monotonicUsec, &boot_id)
	if r < 0 {
		return nil, fmt.Errorf("failed to get monotonic timestamp: %d", syscall.Errno(-r))
	}
	entry.MonotonicTimestamp = uint64(monotonicUsec)
	var c *C.char
	r = C.my_sd_journal_get_cursor(sd_journal_get_cursor, j.cjournal, &c)
	defer C.free(unsafe.Pointer(c))
	if r < 0 {
		return nil, fmt.Errorf("failed to get cursor: %d", syscall.Errno(-r))
	}
	entry.Cursor = C.GoString(c)
	var d unsafe.Pointer
	var l C.size_t
	C.my_sd_journal_restart_data(sd_journal_restart_data, j.cjournal)
	for {
		r = C.my_sd_journal_enumerate_data(sd_journal_enumerate_data, j.cjournal, &d, &l)
		if r == 0 {
			break
		}
		if r < 0 {
			return nil, fmt.Errorf("failed to read message field: %d", syscall.Errno(-r))
		}
		msg := C.GoStringN((*C.char)(d), C.int(l))
		kv := strings.SplitN(msg, "=", 2)
		if len(kv) < 2 {
			return nil, fmt.Errorf("failed to parse field")
		}
		entry.Fields[kv[0]] = kv[1]
	}
	return entry, nil
}
GetEntry returns a full representation of a journal entry with
all key-value pairs of data as well as address fields (cursor, realtime
timestamp and monotonic timestamp)
package sdjournal
import "C"
import (
	"bytes"
	"fmt"
	"strings"
	"sync"
	"syscall"
	"time"
	"unsafe"
)
const (
	SD_JOURNAL_FIELD_MESSAGE           = "MESSAGE"
	SD_JOURNAL_FIELD_MESSAGE_ID        = "MESSAGE_ID"
	SD_JOURNAL_FIELD_PRIORITY          = "PRIORITY"
	SD_JOURNAL_FIELD_CODE_FILE         = "CODE_FILE"
	SD_JOURNAL_FIELD_CODE_LINE         = "CODE_LINE"
	SD_JOURNAL_FIELD_CODE_FUNC         = "CODE_FUNC"
	SD_JOURNAL_FIELD_ERRNO             = "ERRNO"
	SD_JOURNAL_FIELD_SYSLOG_FACILITY   = "SYSLOG_FACILITY"
	SD_JOURNAL_FIELD_SYSLOG_IDENTIFIER = "SYSLOG_IDENTIFIER"
	SD_JOURNAL_FIELD_SYSLOG_PID        = "SYSLOG_PID"
	SD_JOURNAL_FIELD_PID                       = "_PID"
	SD_JOURNAL_FIELD_UID                       = "_UID"
	SD_JOURNAL_FIELD_GID                       = "_GID"
	SD_JOURNAL_FIELD_COMM                      = "_COMM"
	SD_JOURNAL_FIELD_EXE                       = "_EXE"
	SD_JOURNAL_FIELD_CMDLINE                   = "_CMDLINE"
	SD_JOURNAL_FIELD_CAP_EFFECTIVE             = "_CAP_EFFECTIVE"
	SD_JOURNAL_FIELD_AUDIT_SESSION             = "_AUDIT_SESSION"
	SD_JOURNAL_FIELD_AUDIT_LOGINUID            = "_AUDIT_LOGINUID"
	SD_JOURNAL_FIELD_SYSTEMD_CGROUP            = "_SYSTEMD_CGROUP"
	SD_JOURNAL_FIELD_SYSTEMD_SESSION           = "_SYSTEMD_SESSION"
	SD_JOURNAL_FIELD_SYSTEMD_UNIT              = "_SYSTEMD_UNIT"
	SD_JOURNAL_FIELD_SYSTEMD_USER_UNIT         = "_SYSTEMD_USER_UNIT"
	SD_JOURNAL_FIELD_SYSTEMD_OWNER_UID         = "_SYSTEMD_OWNER_UID"
	SD_JOURNAL_FIELD_SYSTEMD_SLICE             = "_SYSTEMD_SLICE"
	SD_JOURNAL_FIELD_SELINUX_CONTEXT           = "_SELINUX_CONTEXT"
	SD_JOURNAL_FIELD_SOURCE_REALTIME_TIMESTAMP = "_SOURCE_REALTIME_TIMESTAMP"
	SD_JOURNAL_FIELD_BOOT_ID                   = "_BOOT_ID"
	SD_JOURNAL_FIELD_MACHINE_ID                = "_MACHINE_ID"
	SD_JOURNAL_FIELD_HOSTNAME                  = "_HOSTNAME"
	SD_JOURNAL_FIELD_TRANSPORT                 = "_TRANSPORT"
	SD_JOURNAL_FIELD_CURSOR              = "__CURSOR"
	SD_JOURNAL_FIELD_REALTIME_TIMESTAMP  = "__REALTIME_TIMESTAMP"
	SD_JOURNAL_FIELD_MONOTONIC_TIMESTAMP = "__MONOTONIC_TIMESTAMP"
)
const (
	SD_JOURNAL_NOP        = int(C.SD_JOURNAL_NOP)
	SD_JOURNAL_APPEND     = int(C.SD_JOURNAL_APPEND)
	SD_JOURNAL_INVALIDATE = int(C.SD_JOURNAL_INVALIDATE)
)
const (
	IndefiniteWait time.Duration = 1<<63 - 1
)
type Journal struct {
	cjournal *C.sd_journal
	mu       sync.Mutex
}
type JournalEntry struct {
	Fields             map[string]string
	Cursor             string
	RealtimeTimestamp  uint64
	MonotonicTimestamp uint64
}
type Match struct {
	Field string
	Value string
}
func (m *Match) String() string {
	return m.Field + "=" + m.Value
}
func NewJournal() (j *Journal, err error) {
	j = &Journal{}
	sd_journal_open, err := getFunction("sd_journal_open")
	if err != nil {
		return nil, err
	}
	r := C.my_sd_journal_open(sd_journal_open, &j.cjournal, C.SD_JOURNAL_LOCAL_ONLY)
	if r < 0 {
		return nil, fmt.Errorf("failed to open journal: %d", syscall.Errno(-r))
	}
	return j, nil
}
func NewJournalFromDir(path string) (j *Journal, err error) {
	j = &Journal{}
	sd_journal_open_directory, err := getFunction("sd_journal_open_directory")
	if err != nil {
		return nil, err
	}
	p := C.CString(path)
	defer C.free(unsafe.Pointer(p))
	r := C.my_sd_journal_open_directory(sd_journal_open_directory, &j.cjournal, p, 0)
	if r < 0 {
		return nil, fmt.Errorf("failed to open journal in directory %q: %d", path, syscall.Errno(-r))
	}
	return j, nil
}
func (j *Journal) Close() error {
	sd_journal_close, err := getFunction("sd_journal_close")
	if err != nil {
		return err
	}
	j.mu.Lock()
	C.my_sd_journal_close(sd_journal_close, j.cjournal)
	j.mu.Unlock()
	return nil
}
func (j *Journal) AddMatch(match string) error {
	sd_journal_add_match, err := getFunction("sd_journal_add_match")
	if err != nil {
		return err
	}
	m := C.CString(match)
	defer C.free(unsafe.Pointer(m))
	j.mu.Lock()
	r := C.my_sd_journal_add_match(sd_journal_add_match, j.cjournal, unsafe.Pointer(m), C.size_t(len(match)))
	j.mu.Unlock()
	if r < 0 {
		return fmt.Errorf("failed to add match: %d", syscall.Errno(-r))
	}
	return nil
}
func (j *Journal) AddDisjunction() error {
	sd_journal_add_disjunction, err := getFunction("sd_journal_add_disjunction")
	if err != nil {
		return err
	}
	j.mu.Lock()
	r := C.my_sd_journal_add_disjunction(sd_journal_add_disjunction, j.cjournal)
	j.mu.Unlock()
	if r < 0 {
		return fmt.Errorf("failed to add a disjunction in the match list: %d", syscall.Errno(-r))
	}
	return nil
}
func (j *Journal) AddConjunction() error {
	sd_journal_add_conjunction, err := getFunction("sd_journal_add_conjunction")
	if err != nil {
		return err
	}
	j.mu.Lock()
	r := C.my_sd_journal_add_conjunction(sd_journal_add_conjunction, j.cjournal)
	j.mu.Unlock()
	if r < 0 {
		return fmt.Errorf("failed to add a conjunction in the match list: %d", syscall.Errno(-r))
	}
	return nil
}
func (j *Journal) FlushMatches() {
	sd_journal_flush_matches, err := getFunction("sd_journal_flush_matches")
	if err != nil {
		return
	}
	j.mu.Lock()
	C.my_sd_journal_flush_matches(sd_journal_flush_matches, j.cjournal)
	j.mu.Unlock()
}
func (j *Journal) Next() (uint64, error) {
	sd_journal_next, err := getFunction("sd_journal_next")
	if err != nil {
		return 0, err
	}
	j.mu.Lock()
	r := C.my_sd_journal_next(sd_journal_next, j.cjournal)
	j.mu.Unlock()
	if r < 0 {
		return 0, fmt.Errorf("failed to iterate journal: %d", syscall.Errno(-r))
	}
	return uint64(r), nil
}
func (j *Journal) NextSkip(skip uint64) (uint64, error) {
	sd_journal_next_skip, err := getFunction("sd_journal_next_skip")
	if err != nil {
		return 0, err
	}
	j.mu.Lock()
	r := C.my_sd_journal_next_skip(sd_journal_next_skip, j.cjournal, C.uint64_t(skip))
	j.mu.Unlock()
	if r < 0 {
		return 0, fmt.Errorf("failed to iterate journal: %d", syscall.Errno(-r))
	}
	return uint64(r), nil
}
func (j *Journal) Previous() (uint64, error) {
	sd_journal_previous, err := getFunction("sd_journal_previous")
	if err != nil {
		return 0, err
	}
	j.mu.Lock()
	r := C.my_sd_journal_previous(sd_journal_previous, j.cjournal)
	j.mu.Unlock()
	if r < 0 {
		return 0, fmt.Errorf("failed to iterate journal: %d", syscall.Errno(-r))
	}
	return uint64(r), nil
}
func (j *Journal) PreviousSkip(skip uint64) (uint64, error) {
	sd_journal_previous_skip, err := getFunction("sd_journal_previous_skip")
	if err != nil {
		return 0, err
	}
	j.mu.Lock()
	r := C.my_sd_journal_previous_skip(sd_journal_previous_skip, j.cjournal, C.uint64_t(skip))
	j.mu.Unlock()
	if r < 0 {
		return 0, fmt.Errorf("failed to iterate journal: %d", syscall.Errno(-r))
	}
	return uint64(r), nil
}
func (j *Journal) getData(field string) (unsafe.Pointer, C.int, error) {
	sd_journal_get_data, err := getFunction("sd_journal_get_data")
	if err != nil {
		return nil, 0, err
	}
	f := C.CString(field)
	defer C.free(unsafe.Pointer(f))
	var d unsafe.Pointer
	var l C.size_t
	j.mu.Lock()
	r := C.my_sd_journal_get_data(sd_journal_get_data, j.cjournal, f, &d, &l)
	j.mu.Unlock()
	if r < 0 {
		return nil, 0, fmt.Errorf("failed to read message: %d", syscall.Errno(-r))
	}
	return d, C.int(l), nil
}
func (j *Journal) GetData(field string) (string, error) {
	d, l, err := j.getData(field)
	if err != nil {
		return "", err
	}
	return C.GoStringN((*C.char)(d), l), nil
}
func (j *Journal) GetDataValue(field string) (string, error) {
	val, err := j.GetData(field)
	if err != nil {
		return "", err
	}
	return strings.SplitN(val, "=", 2)[1], nil
}
func (j *Journal) GetDataBytes(field string) ([]byte, error) {
	d, l, err := j.getData(field)
	if err != nil {
		return nil, err
	}
	return C.GoBytes(d, l), nil
}
func (j *Journal) GetDataValueBytes(field string) ([]byte, error) {
	val, err := j.GetDataBytes(field)
	if err != nil {
		return nil, err
	}
	return bytes.SplitN(val, []byte("="), 2)[1], nil
}