func (s *Service) ProcessEntry(hostname *string) { var realtime C.uint64_t r := C.sd_journal_get_realtime_usec(s.Journal, &realtime) if r < 0 { panic(fmt.Sprintf("failed to get realtime timestamp: %s", C.strerror(-r))) } var cursor *C.char r = C.sd_journal_get_cursor(s.Journal, &cursor) if r < 0 { panic(fmt.Sprintf("failed to get cursor: %s", C.strerror(-r))) } row := make(map[string]interface{}) timestamp := time.Unix(int64(realtime/1000000), int64(realtime%1000000)).UTC() row["ts"] = timestamp.Format("2006-01-02T15:04:05Z") row["host"] = hostname s.ProcessEntryFields(row) message, _ := json.Marshal(row) indexName := fmt.Sprintf("%v-%v", s.Config.IndexPrefix, timestamp.Format("2006-01-02")) cursorId := C.GoString(cursor) s.Indexer.Index( indexName, // index "journal", // type cursorId, // id "", // ttl nil, // date string(message), // content false) // immediate index refresh }
func (s *journald) followJournal(logWatcher *logger.LogWatcher, config logger.ReadConfig, j *C.sd_journal, pfd [2]C.int, cursor string) { s.readers.mu.Lock() s.readers.readers[logWatcher] = logWatcher s.readers.mu.Unlock() go func() { // Keep copying journal data out until we're notified to stop // or we hit an error. status := C.wait_for_data_or_close(j, pfd[0]) for status == 1 { cursor = s.drainJournal(logWatcher, config, j, cursor) status = C.wait_for_data_or_close(j, pfd[0]) } if status < 0 { cerrstr := C.strerror(C.int(-status)) errstr := C.GoString(cerrstr) fmtstr := "error %q while attempting to follow journal for container %q" logrus.Errorf(fmtstr, errstr, s.vars["CONTAINER_ID_FULL"]) } // Clean up. C.close(pfd[0]) s.readers.mu.Lock() delete(s.readers.readers, logWatcher) s.readers.mu.Unlock() C.sd_journal_close(j) close(logWatcher.Msg) }() // Wait until we're told to stop. select { case <-logWatcher.WatchClose(): // Notify the other goroutine that its work is done. C.close(pfd[1]) } }
func OpenUTun() (*os.File, error) { fd := C.utun_open() if fd < 0 { return nil, errors.New(C.GoString(C.strerror(-fd))) } return os.NewFile(uintptr(fd), "/dev/tun0"), nil }
func mount(device, target, mType string, flag uintptr, data string) error { isNullFS := false xs := strings.Split(data, ",") for _, x := range xs { if x == "bind" { isNullFS = true } } options := []string{"fspath", target} if isNullFS { options = append(options, "fstype", "nullfs", "target", device) } else { options = append(options, "fstype", mType, "from", device) } rawOptions := allocateIOVecs(options) for _, rawOption := range rawOptions { defer C.free(rawOption.iov_base) } if errno := C.nmount(&rawOptions[0], C.uint(len(options)), C.int(flag)); errno != 0 { reason := C.GoString(C.strerror(*C.__error())) return fmt.Errorf("Failed to call nmount: %s", reason) } return nil }
// send writes an arbitrary event and sync through uinput, converting the // return code into an appropriate error. func (i linuxInputer) send(t C.uint, c C.uint, v C.int) error { var rc C.int if rc = C.libevdev_uinput_write_event(i.uidev, t, c, v); rc < 0 { e := C.strerror(rc) return fmt.Errorf("Error %d sending event: %s", rc, C.GoString(e)) } return nil }
func (r *Rados) ClusterConnect() error { cerr := C.rados_connect(*r.cluster) if cerr < 0 { log.Println("error is", C.GoString(C.strerror(-cerr))) return errors.New("connect to ceph failed") } return nil }
func (s *Service) ProcessStream() { s.Indexer.Start() defer s.Indexer.Stop() for { r := C.sd_journal_next(s.Journal) if r < 0 { log.Fatalf("failed to iterate to next entry: %s\n", C.strerror(-r)) } if r == 0 { r = C.sd_journal_wait(s.Journal, 1000000) if r < 0 { log.Fatalf("failed to wait for changes: %s\n", C.strerror(-r)) } continue } s.ProcessEntry() } }
func (s *Service) ProcessStream(hostname *string) { s.Indexer.Start() defer s.Indexer.Stop() for { r := C.sd_journal_next(s.Journal) if r < 0 { panic(fmt.Sprintf("failed to iterate to next entry: %s", C.strerror(-r))) } if r == 0 { r = C.sd_journal_wait(s.Journal, 1000000) if r < 0 { panic(fmt.Sprintf("failed to wait for changes: %s", C.strerror(-r))) } continue } s.ProcessEntry(hostname) } }
func (s *Service) InitJournal() { r := C.sd_journal_open(&s.Journal, C.SD_JOURNAL_LOCAL_ONLY) if r < 0 { log.Fatalf("failed to open journal: %s\n", C.strerror(-r)) } bytes, err := ioutil.ReadFile(s.Config.State) if err == nil { s.Cursor = string(bytes) } if s.Cursor != "" { r = C.sd_journal_seek_cursor(s.Journal, C.CString(s.Cursor)) if r < 0 { log.Fatalf("failed to seek journal: %s\n", C.strerror(-r)) } r = C.sd_journal_next_skip(s.Journal, 1) if r < 0 { log.Fatalf("failed to skip current journal entry: %s\n", C.strerror(-r)) } } }
func (s *Service) InitJournal() { r := C.sd_journal_open(&s.Journal, C.SD_JOURNAL_LOCAL_ONLY) if r < 0 { panic(fmt.Sprintf("failed to open journal: %s", C.strerror(-r))) } bytes, err := ioutil.ReadFile(*elasticCursorFile) if err == nil { s.Cursor = string(bytes) } if s.Cursor != "" { r = C.sd_journal_seek_cursor(s.Journal, C.CString(s.Cursor)) if r < 0 { panic(fmt.Sprintf("failed to seek journal: %s", C.strerror(-r))) } r = C.sd_journal_next_skip(s.Journal, 1) if r < 0 { panic(fmt.Sprintf("failed to skip current journal entry: %s", C.strerror(-r))) } } }
func (r *Rados) IoCtxCreate(poolname string) (*RadosIoCtx, error) { cpoolname := C.CString(poolname) defer func() { C.free(unsafe.Pointer(cpoolname)) }() var ctx C.rados_ioctx_t cerr := C.rados_ioctx_create(*r.cluster, cpoolname, &ctx) if cerr < 0 { return nil, errors.New("create io contxt failed:" + C.GoString(C.strerror(-cerr))) } return &RadosIoCtx{&ctx}, nil }
// Run runs xhyve hypervisor. func Run(params []string, newPtyCh chan string) error { newPty = newPtyCh argc := C.int(len(params)) argv = make([]*C.char, argc) for i, arg := range params { argv[i] = C.CString(arg) } // Runs xhyve and blocks. if err := C.run_xhyve(argc, &argv[0]); err != 0 { fmt.Printf("ERROR => %s\n", C.GoString(C.strerror(err))) return fmt.Errorf("Error initializing hypervisor") } return nil }
func strerror(i C.int) error { return errors.New(C.GoString(C.strerror(-i))) }
// strerror is a utility wrapper around the libc strerror() function. It returns // a Go string containing the text of the error. func strerror(cerr C.int) string { return C.GoString(C.strerror(-cerr)) }
func (e RadosError) Error() string { return fmt.Sprintf("rados: %s", C.GoString(C.strerror(C.int(-e)))) }
func NewInput(name string, flags FeatureFlag) (*linuxInputer, error) { var rc C.int var dev *C.struct_libevdev var uidev *C.struct_libevdev_uinput dev = C.libevdev_new() C.libevdev_set_name(dev, C.CString(name)) // Build up some basic absolute axis defaults var abs C.struct_input_absinfo abs.value = 0 abs.minimum = -100 abs.maximum = 100 abs.fuzz = 5 abs.flat = 0 abs.resolution = 1 // Absolute axis (sticks) C.libevdev_enable_event_type(dev, C.EV_ABS) if flags&LeftAnalogStick == LeftAnalogStick { C.libevdev_enable_event_code(dev, C.EV_ABS, C.ABS_X, unsafe.Pointer(&abs)) C.libevdev_enable_event_code(dev, C.EV_ABS, C.ABS_Y, unsafe.Pointer(&abs)) } if flags&RightAnalogStick == RightAnalogStick { C.libevdev_enable_event_code(dev, C.EV_ABS, C.ABS_RX, unsafe.Pointer(&abs)) C.libevdev_enable_event_code(dev, C.EV_ABS, C.ABS_RY, unsafe.Pointer(&abs)) } // Face buttons C.libevdev_enable_event_type(dev, C.EV_KEY) if flags&StartButton == StartButton { C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_START, nil) } if flags&SelectButton == SelectButton { C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_SELECT, nil) } if flags&ABButtons == ABButtons { C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_A, nil) C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_B, nil) } if flags&XYButtons == XYButtons { C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_X, nil) C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_Y, nil) } if flags&DPad == DPad { C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_DPAD_UP, nil) C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_DPAD_DOWN, nil) C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_DPAD_LEFT, nil) C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_DPAD_RIGHT, nil) } // Open uinput f, err := os.OpenFile("/dev/uinput", os.O_RDWR, 0660) if err != nil { e := C.strerror(rc) return nil, fmt.Errorf("Error %d (%s) opening /dev/uinput : %s", rc, C.GoString(e), err) } // Get file hanadle var fd C.int fd = C.int(f.Fd()) // Create new uinput device rc = C.libevdev_uinput_create_from_device(dev, fd, &uidev) if rc < 0 { f.Close() e := C.strerror(rc) return nil, fmt.Errorf("Error %d creating uinput device: %s", rc, C.GoString(e)) } return &linuxInputer{ uidev: uidev, f: f, }, nil }
func (s *journald) readLogs(logWatcher *logger.LogWatcher, config logger.ReadConfig) { var j *C.sd_journal var cmatch *C.char var stamp C.uint64_t var sinceUnixMicro uint64 var pipes [2]C.int cursor := "" // Get a handle to the journal. rc := C.sd_journal_open(&j, C.int(0)) if rc != 0 { logWatcher.Err <- fmt.Errorf("error opening journal") close(logWatcher.Msg) return } // If we end up following the log, we can set the journal context // pointer and the channel pointer to nil so that we won't close them // here, potentially while the goroutine that uses them is still // running. Otherwise, close them when we return from this function. following := false defer func(pfollowing *bool) { if !*pfollowing { C.sd_journal_close(j) close(logWatcher.Msg) } }(&following) // Remove limits on the size of data items that we'll retrieve. rc = C.sd_journal_set_data_threshold(j, C.size_t(0)) if rc != 0 { logWatcher.Err <- fmt.Errorf("error setting journal data threshold") return } // Add a match to have the library do the searching for us. cmatch = C.CString("CONTAINER_ID_FULL=" + s.vars["CONTAINER_ID_FULL"]) defer C.free(unsafe.Pointer(cmatch)) rc = C.sd_journal_add_match(j, unsafe.Pointer(cmatch), C.strlen(cmatch)) if rc != 0 { logWatcher.Err <- fmt.Errorf("error setting journal match") return } // If we have a cutoff time, convert it to Unix time once. if !config.Since.IsZero() { nano := config.Since.UnixNano() sinceUnixMicro = uint64(nano / 1000) } if config.Tail > 0 { lines := config.Tail // Start at the end of the journal. if C.sd_journal_seek_tail(j) < 0 { logWatcher.Err <- fmt.Errorf("error seeking to end of journal") return } if C.sd_journal_previous(j) < 0 { logWatcher.Err <- fmt.Errorf("error backtracking to previous journal entry") return } // Walk backward. for lines > 0 { // Stop if the entry time is before our cutoff. // We'll need the entry time if it isn't, so go // ahead and parse it now. if C.sd_journal_get_realtime_usec(j, &stamp) != 0 { break } else { // Compare the timestamp on the entry // to our threshold value. if sinceUnixMicro != 0 && sinceUnixMicro > uint64(stamp) { break } } lines-- // If we're at the start of the journal, or // don't need to back up past any more entries, // stop. if lines == 0 || C.sd_journal_previous(j) <= 0 { break } } } else { // Start at the beginning of the journal. if C.sd_journal_seek_head(j) < 0 { logWatcher.Err <- fmt.Errorf("error seeking to start of journal") return } // If we have a cutoff date, fast-forward to it. if sinceUnixMicro != 0 && C.sd_journal_seek_realtime_usec(j, C.uint64_t(sinceUnixMicro)) != 0 { logWatcher.Err <- fmt.Errorf("error seeking to start time in journal") return } if C.sd_journal_next(j) < 0 { logWatcher.Err <- fmt.Errorf("error skipping to next journal entry") return } } cursor = s.drainJournal(logWatcher, config, j, "") if config.Follow { // Allocate a descriptor for following the journal, if we'll // need one. Do it here so that we can report if it fails. if fd := C.sd_journal_get_fd(j); fd < C.int(0) { logWatcher.Err <- fmt.Errorf("error opening journald follow descriptor: %q", C.GoString(C.strerror(-fd))) } else { // Create a pipe that we can poll at the same time as // the journald descriptor. if C.pipe(&pipes[0]) == C.int(-1) { logWatcher.Err <- fmt.Errorf("error opening journald close notification pipe") } else { s.followJournal(logWatcher, config, j, pipes, cursor) // Let followJournal handle freeing the journal context // object and closing the channel. following = true } } } return }