func loadSystemRoots() (*CertPool, error) { roots := NewCertPool() var data C.CFDataRef = nil var untrustedData C.CFDataRef = nil err := C.FetchPEMRoots(&data, &untrustedData) if err == -1 { // TODO: better error message return nil, errors.New("crypto/x509: failed to load darwin system roots with cgo") } defer C.CFRelease(C.CFTypeRef(data)) buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data))) roots.AppendCertsFromPEM(buf) if untrustedData == nil { return roots, nil } defer C.CFRelease(C.CFTypeRef(untrustedData)) buf = C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(untrustedData)), C.int(C.CFDataGetLength(untrustedData))) untrustedRoots := NewCertPool() untrustedRoots.AppendCertsFromPEM(buf) trustedRoots := NewCertPool() for _, c := range roots.certs { if !untrustedRoots.contains(c) { trustedRoots.AddCert(c) } } return trustedRoots, nil }
// Given a PostScript font name the function will attempt to load a matching // font and return a font object back to the caller. // // If no font with the given name is found a font that most closely resembles // what was requested will be returned instead based on the platform's fallback // mechanism. // More details on the mechanism can be found at: // https://developer.apple.com/library/mac/documentation/Carbon/Reference/CTFontRef/#//apple_ref/c/func/CTFontCreateWithName // // The function returns an error if loading the font failed for any reason. func NewFontWithName(fontName string) (font *Font, err error) { cfname := GoStringToCFString(fontName) defer C.CFRelease(C.CFTypeRef(cfname)) font = &Font{ ref: C.CTFontCreateWithName(cfname, 0.0, nil), } if font.ref == nil { err = fmt.Errorf("CoreText failed to craete a CTFontRef object with name '%s'", fontName) return } runtime.SetFinalizer(font, (*Font).release) name := C.CTFontCopyPostScriptName(font.ref) defer C.CFRelease(C.CFTypeRef(name)) family := C.CTFontCopyFamilyName(font.ref) defer C.CFRelease(C.CFTypeRef(family)) display := C.CTFontCopyDisplayName(font.ref) defer C.CFRelease(C.CFTypeRef(display)) font.name = CFStringToGoString(name) font.family = CFStringToGoString(family) font.display = CFStringToGoString(display) return }
func CGImageCreateWithImageNoCopy(img image.Image) (cgimg C.CGImageRef, err error) { var data imageData if data, err = extractImageData(img); err != nil { return } provider := C.CGDataProviderCreateWithData( nil, unsafe.Pointer(&data.pixels[0]), C.size_t(len(data.pixels)), nil, ) cgimg = C.CGImageCreate( C.size_t(data.width), C.size_t(data.height), C.size_t(data.bpc), C.size_t(data.bpp), C.size_t(data.stride), data.colors, data.info, provider, nil, false, C.kCGRenderingIntentDefault, ) C.CFRelease(provider) C.CFRelease(data.colors) return }
// GetAllAccountNames returns a list of all account names for the // given service name in the default keychain. func GetAllAccountNames(serviceName string) (accountNames []string, err error) { var serviceNameString C.CFStringRef if serviceNameString, err = _UTF8StringToCFString(serviceName); err != nil { return } defer C.CFRelease(C.CFTypeRef(serviceNameString)) query := map[C.CFTypeRef]C.CFTypeRef{ secClass: secClassGenericPassword, secAttrService: C.CFTypeRef(serviceNameString), secMatchLimit: secMatchLimitAll, secReturnAttributes: C.CFTypeRef(C.kCFBooleanTrue), } queryDict := mapToCFDictionary(query) defer C.CFRelease(C.CFTypeRef(queryDict)) var resultsRef C.CFTypeRef errCode := C.SecItemCopyMatching(queryDict, &resultsRef) err = newKeychainError(errCode) if err == ErrItemNotFound { return []string{}, nil } else if err != nil { return nil, err } defer C.CFRelease(resultsRef) // The resultsRef should always be an array (because kSecReturnAttributes is true) // but it's a good sanity check and useful if want to support kSecReturnRef in the future. typeID := C.CFGetTypeID(resultsRef) if typeID != C.CFArrayGetTypeID() { typeDesc := C.CFCopyTypeIDDescription(typeID) defer C.CFRelease(C.CFTypeRef(typeDesc)) err = fmt.Errorf("Invalid result type: %s", _CFStringToUTF8String(typeDesc)) return } results := _CFArrayToArray(C.CFArrayRef(resultsRef)) for _, result := range results { m := _CFDictionaryToMap(C.CFDictionaryRef(result)) resultServiceName := _CFStringToUTF8String(C.CFStringRef(m[secAttrService])) if resultServiceName != serviceName { err = fmt.Errorf("Expected service name %s, got %s", serviceName, resultServiceName) return } accountName := _CFStringToUTF8String(C.CFStringRef(m[secAttrAccount])) accountNames = append(accountNames, accountName) } return }
// Covert attributes to CFDictionaryRef. You need to release the result. func convertAttr(attr map[string]interface{}) (C.CFDictionaryRef, error) { m := make(map[C.CFTypeRef]C.CFTypeRef) for key, i := range attr { var valueRef C.CFTypeRef switch i.(type) { default: return nil, fmt.Errorf("Unsupported value type for keychain item: %v", reflect.TypeOf(i)) case C.CFTypeRef: valueRef = i.(C.CFTypeRef) case bool: if i == true { valueRef = C.CFTypeRef(C.kCFBooleanTrue) } else { valueRef = C.CFTypeRef(C.kCFBooleanFalse) } case []byte: bytesRef, err := bytesToCFData(i.([]byte)) if err != nil { return nil, err } valueRef = C.CFTypeRef(bytesRef) defer C.CFRelease(valueRef) case string: stringRef, err := stringToCFString(i.(string)) if err != nil { return nil, err } valueRef = C.CFTypeRef(stringRef) defer C.CFRelease(valueRef) case Convertable: convertedRef, err := (i.(Convertable)).Convert() if err != nil { return nil, err } valueRef = C.CFTypeRef(convertedRef) defer C.CFRelease(valueRef) } keyRef, err := stringToCFString(key) if err != nil { return nil, err } m[C.CFTypeRef(keyRef)] = valueRef } cfDict, err := mapToCFDictionary(m) if err != nil { return nil, err } return cfDict, nil }
// QueryItem returns a list of query results. func QueryItem(item Item) ([]QueryResult, error) { cfDict, err := convertAttr(item.attr) if err != nil { return nil, err } defer C.CFRelease(C.CFTypeRef(cfDict)) var resultsRef C.CFTypeRef errCode := C.SecItemCopyMatching(cfDict, &resultsRef) if Error(errCode) == ErrorItemNotFound { return nil, nil } err = checkError(errCode) if err != nil { return nil, err } defer C.CFRelease(resultsRef) results := make([]QueryResult, 0, 1) typeID := C.CFGetTypeID(resultsRef) if typeID == C.CFArrayGetTypeID() { arr := cfArrayToArray(C.CFArrayRef(resultsRef)) for _, dictRef := range arr { item, err := convertResult(C.CFDictionaryRef(dictRef)) if err != nil { return nil, err } results = append(results, *item) } } else if typeID == C.CFDictionaryGetTypeID() { item, err := convertResult(C.CFDictionaryRef(resultsRef)) if err != nil { return nil, err } results = append(results, *item) } else if typeID == C.CFDataGetTypeID() { b, err := cfDataToBytes(C.CFDataRef(resultsRef)) if err != nil { return nil, err } item := QueryResult{Data: b} results = append(results, item) } else { return nil, fmt.Errorf("Invalid result type: %s", cfTypeDescription(resultsRef)) } return results, nil }
func (w *Watcher) watchPath(path string, options *Options) error { path, _ = filepath.Abs(path) w.wmut.Lock() _, found := w.watches[path] w.wmut.Unlock() if !found { cPaths := C.ArrayCreateMutable(C.int(1)) defer C.CFRelease(C.CFTypeRef(cPaths)) cpath := C.CString(path) defer C.free(unsafe.Pointer(cpath)) str := C.CFStringCreateWithCString(nil, cpath, C.kCFStringEncodingUTF8) C.CFArrayAppendValue(cPaths, unsafe.Pointer(str)) context := C.FSEventStreamContext{info: unsafe.Pointer(&w.internalEvent)} latency := C.CFTimeInterval(0) if options != nil && options.Throttle { latency = C.CFTimeInterval(options.ThrottleDuration / time.Second) } stream := C.EventStreamCreate(&context, cPaths, C.kFSEventStreamEventIdSinceNow+(1<<64), latency) w.wmut.Lock() w.watches[path] = stream w.wmut.Unlock() C.FSEventStreamScheduleWithRunLoop(stream, w.rlref, C.kCFRunLoopDefaultMode) C.FSEventStreamStart(stream) } return nil }
func CaptureRect(rect image.Rectangle) (*image.RGBA, error) { displayID := C.CGMainDisplayID() width := int(C.CGDisplayPixelsWide(displayID)) rawData := C.CGDataProviderCopyData(C.CGImageGetDataProvider(C.CGDisplayCreateImage(displayID))) length := int(C.CFDataGetLength(rawData)) ptr := unsafe.Pointer(C.CFDataGetBytePtr(rawData)) var slice []byte hdrp := (*reflect.SliceHeader)(unsafe.Pointer(&slice)) hdrp.Data = uintptr(ptr) hdrp.Len = length hdrp.Cap = length imageBytes := make([]byte, length) for i := 0; i < length; i += 4 { imageBytes[i], imageBytes[i+2], imageBytes[i+1], imageBytes[i+3] = slice[i+2], slice[i], slice[i+1], slice[i+3] } C.CFRelease(rawData) img := &image.RGBA{Pix: imageBytes, Stride: 4 * width, Rect: rect} return img, nil }
func NewCFError(c C.CFErrorRef) *CFError { e := &CFError{ Domain: convertCFStringToString(C.CFErrorGetDomain(c)), Code: int(C.CFErrorGetCode(c)), } cfDict := C.CFErrorCopyUserInfo(c) defer C.CFRelease(C.CFTypeRef(cfDict)) if userInfo, err := convertCFDictionaryToMap(cfDict); err == nil { // on error, skip user info e.UserInfo = userInfo } cfStr := C.CFErrorCopyDescription(c) defer C.CFRelease(C.CFTypeRef(cfStr)) e.Description = convertCFStringToString(cfStr) return e }
// ExportFromKeychain ... func ExportFromKeychain(itemRefsToExport []C.CFTypeRef, outputFilePath string, isAskForPassword bool) error { passphraseCString := C.CString("") defer C.free(unsafe.Pointer(passphraseCString)) var exportedData C.CFDataRef var exportParams C.SecItemImportExportKeyParameters exportParams.keyUsage = nil exportParams.keyAttributes = nil exportParams.version = C.SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION if isAskForPassword { exportParams.flags = C.kSecKeySecurePassphrase exportParams.passphrase = nil exportParams.alertTitle = nil promptText := C.CString("Enter a password which will be used to protect the exported items") defer C.free(unsafe.Pointer(promptText)) exportParams.alertPrompt = convertCStringToCFString(promptText) } else { exportParams.flags = 0 exportParams.passphrase = (C.CFTypeRef)(convertCStringToCFString(passphraseCString)) exportParams.alertTitle = nil exportParams.alertPrompt = nil } // create a C array from the input ptr := (*unsafe.Pointer)(&itemRefsToExport[0]) cfArrayForExport := C.CFArrayCreate( C.kCFAllocatorDefault, ptr, C.CFIndex(len(itemRefsToExport)), &C.kCFTypeArrayCallBacks) // do the export! status := C.SecItemExport(C.CFTypeRef(cfArrayForExport), C.kSecFormatPKCS12, 0, //C.kSecItemPemArmour, // Use kSecItemPemArmour to add PEM armour - the .p12 generated by Keychain Access.app does NOT have PEM armour &exportParams, &exportedData) if status != C.errSecSuccess { return fmt.Errorf("SecItemExport: error (OSStatus): %d", status) } // exportedData now contains your PKCS12 data // make sure it'll be released properly! defer C.CFRelease(C.CFTypeRef(exportedData)) dataBytes := convertCFDataRefToGoBytes(exportedData) if dataBytes == nil || len(dataBytes) < 1 { return errors.New("ExportFromKeychain: failed to convert export data - nil or empty") } if err := fileutil.WriteBytesToFile(outputFilePath, dataBytes); err != nil { return fmt.Errorf("ExportFromKeychain: failed to write into file: %s", err) } log.Debug("Export - success") return nil }
// AddGenericPassword adds a generic password with the given // attributes to the default keychain. func AddGenericPassword(attributes *GenericPasswordAttributes) (err error) { if err = attributes.CheckValidity(); err != nil { return } var serviceNameString C.CFStringRef if serviceNameString, err = _UTF8StringToCFString(attributes.ServiceName); err != nil { return } defer C.CFRelease(C.CFTypeRef(serviceNameString)) var accountNameString C.CFStringRef if accountNameString, err = _UTF8StringToCFString(attributes.AccountName); err != nil { return } defer C.CFRelease(C.CFTypeRef(accountNameString)) dataBytes := bytesToCFData(attributes.Password) defer C.CFRelease(C.CFTypeRef(dataBytes)) query := map[C.CFTypeRef]C.CFTypeRef{ secClass: secClassGenericPassword, secAttrService: C.CFTypeRef(serviceNameString), secAttrAccount: C.CFTypeRef(accountNameString), secValueData: C.CFTypeRef(dataBytes), } access, err := createAccess(attributes.ServiceName, attributes.TrustedApplications) if err != nil { return } if access != nil { defer C.CFRelease(C.CFTypeRef(access)) query[secAttrAccess] = C.CFTypeRef(access) } queryDict := mapToCFDictionary(query) defer C.CFRelease(C.CFTypeRef(queryDict)) errCode := C.SecItemAdd(queryDict, nil) err = newKeychainError(errCode) return }
// The returned SecAccessRef, if non-nil, must be released via CFRelease. func createEmptyAccess(label string) (C.SecAccessRef, error) { var err error var labelRef C.CFStringRef if labelRef, err = _UTF8StringToCFString(label); err != nil { return nil, err } defer C.CFRelease(C.CFTypeRef(labelRef)) var access C.SecAccessRef trustedApplicationsArray := arrayToCFArray([]C.CFTypeRef{}) defer C.CFRelease(C.CFTypeRef(trustedApplicationsArray)) if err = newKeychainError(C.SecAccessCreate(labelRef, trustedApplicationsArray, &access)); err != nil { return nil, err } return access, nil }
func stringToCFString(str string, callback func(cfStr C.CFStringRef)) { cStr := C.CString(str) cfStr := C.CFStringCreateWithCString(nil, cStr, C.kCFStringEncodingMacRoman) defer C.free(unsafe.Pointer(cStr)) defer C.CFRelease((C.CFTypeRef)(cfStr)) callback(cfStr) }
func (k *keychain) Keys() ([]string, error) { serviceRef, err := _UTF8StringToCFString(k.Service) if err != nil { return nil, err } defer C.CFRelease(C.CFTypeRef(serviceRef)) query := map[C.CFTypeRef]C.CFTypeRef{ C.CFTypeRef(C.kSecClass): C.CFTypeRef(C.kSecClassGenericPassword), C.CFTypeRef(C.kSecAttrService): C.CFTypeRef(serviceRef), C.CFTypeRef(C.kSecMatchLimit): C.CFTypeRef(C.kSecMatchLimitAll), C.CFTypeRef(C.kSecReturnAttributes): C.CFTypeRef(C.kCFBooleanTrue), } kref, err := openKeychain(k.Path) if err != nil { return nil, err } searchArray := arrayToCFArray([]C.CFTypeRef{C.CFTypeRef(kref)}) defer C.CFRelease(C.CFTypeRef(searchArray)) query[C.CFTypeRef(C.kSecMatchSearchList)] = C.CFTypeRef(searchArray) queryDict := mapToCFDictionary(query) defer C.CFRelease(C.CFTypeRef(queryDict)) var resultsRef C.CFTypeRef if err = newKeychainError(C.SecItemCopyMatching(queryDict, &resultsRef)); err == errItemNotFound { return nil, nil } else if err != nil { return nil, err } defer C.CFRelease(resultsRef) var accountNames = []string{} for _, result := range _CFArrayToArray(C.CFArrayRef(resultsRef)) { m := _CFDictionaryToMap(C.CFDictionaryRef(result)) accountName := _CFStringToUTF8String(C.CFStringRef(m[C.CFTypeRef(C.kSecAttrAccount)])) accountNames = append(accountNames, accountName) } return accountNames, nil }
func CFNetServiceSetTXTData(cns *CFNetService, data []byte) bool { p := unsafe.Pointer(nil) if data != nil && len(data) > 0 { p = unsafe.Pointer(&data[0]) } data_ := C.CFDataCreate(nil, (*C.UInt8)(p), C.CFIndex(len(data))) retval := C.CFNetServiceSetTXTData(cns.ref, data_) C.CFRelease((C.CFTypeRef)(data_)) return retval != 0 }
// DeleteItem removes a Item func DeleteItem(item Item) error { cfDict, err := convertAttr(item.attr) if err != nil { return err } defer C.CFRelease(C.CFTypeRef(cfDict)) errCode := C.SecItemDelete(cfDict) return checkError(errCode) }
func (self *Clipboard) addImage(img image.Image) (err error) { var i C.CGImageRef if i, err = CGImageCreateWithImage(img); err == nil { C.Clipboard_AddImage(self.ref, i) C.CFRelease(C.CFTypeRef(i)) } return }
// Attributes provides metadata about the voice. // The attributes for a voice are described in the documentation for [NSSpeechSynthesizer attributesForVoice]. // This functionality is undocumented in the Carbon Speech Synthesis Manager. func (vs VoiceSpec) Attributes() (VoiceAttributes, error) { var va VoiceAttributes oserr := C.GetVoiceInfo((*C.VoiceSpec)(&vs), C.soVoiceAttributes, unsafe.Pointer(&va.cfd)) if oserr != 0 { return va, osError(oserr) } runtime.SetFinalizer(&va, func(va *VoiceAttributes) { C.CFRelease(C.CFTypeRef(va.cfd)) }) return va, nil }
// AddItem adds a Item func AddItem(item Item) error { cfDict, err := convertAttr(item.attr) if err != nil { return err } defer C.CFRelease(C.CFTypeRef(cfDict)) errCode := C.SecItemAdd(cfDict, nil) err = checkError(errCode) return err }
// FindAndRemoveGenericPassword finds a generic password with the // given attributes in the default keychain and removes it if // found. If not found, an error is returned. func FindAndRemoveGenericPassword(attributes *GenericPasswordAttributes) error { itemRef, err := findGenericPasswordItem(attributes) if err != nil { return err } defer C.CFRelease(C.CFTypeRef(itemRef)) errCode := C.SecKeychainItemDelete(itemRef) return newKeychainError(errCode) }
func iterateDevices(action func(device C.IOHIDDeviceRef) bool) cleanupDeviceManagerFn { mgr := C.IOHIDManagerCreate(C.kCFAllocatorDefault, C.kIOHIDOptionsTypeNone) C.IOHIDManagerSetDeviceMatching(mgr, nil) C.IOHIDManagerOpen(mgr, C.kIOHIDOptionsTypeNone) allDevicesSet := C.IOHIDManagerCopyDevices(mgr) defer C.CFRelease(C.CFTypeRef(allDevicesSet)) devCnt := C.CFSetGetCount(allDevicesSet) allDevices := make([]unsafe.Pointer, uint64(devCnt)) C.CFSetGetValues(allDevicesSet, &allDevices[0]) for _, pDev := range allDevices { if !action(C.IOHIDDeviceRef(pDev)) { break } } return func() { C.IOHIDManagerClose(mgr, C.kIOHIDOptionsTypeNone) C.CFRelease(C.CFTypeRef(mgr)) } }
// https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/Reference/reference.html#jumpTo_8 func (s Stream) Paths() []string { cpaths := C.FSEventStreamCopyPathsBeingWatched(s.cstream) defer C.CFRelease(C.CFTypeRef(cpaths)) count := C.CFArrayGetCount(cpaths) paths := make([]string, count) var i C.CFIndex for ; i < count; i++ { cpath := C.CFStringRef(C.CFArrayGetValueAtIndex(cpaths, i)) paths[i] = fromCFString(cpath) } return paths }
func (ke keychainError) Error() string { errorMessageCFString := C.SecCopyErrorMessageString(C.OSStatus(ke), nil) defer C.CFRelease(C.CFTypeRef(errorMessageCFString)) errorMessageCString := C.CFStringGetCStringPtr(errorMessageCFString, C.kCFStringEncodingASCII) if errorMessageCString != nil { return C.GoString(errorMessageCString) } return fmt.Sprintf("keychainError with unknown error code %d", C.OSStatus(ke)) }
func buildFont(f C.CTFontRef) []byte { ctags := C.CTFontCopyAvailableTables(f, C.kCTFontTableOptionExcludeSynthetic) tagsCount := C.CFArrayGetCount(ctags) var tags []uint32 var dataRefs []C.CFDataRef var dataLens []uint32 for i := C.CFIndex(0); i < tagsCount; i++ { tag := (C.CTFontTableTag)((uintptr)(C.CFArrayGetValueAtIndex(ctags, i))) dataRef := C.CTFontCopyTable(f, tag, 0) // retained tags = append(tags, uint32(tag)) dataRefs = append(dataRefs, dataRef) dataLens = append(dataLens, uint32(C.CFDataGetLength(dataRef))) } totalLen := 0 for _, l := range dataLens { totalLen += int(l) } // Big-endian output. buf := make([]byte, 0, 12+16*len(tags)+totalLen) write16 := func(x uint16) { buf = append(buf, byte(x>>8), byte(x)) } write32 := func(x uint32) { buf = append(buf, byte(x>>24), byte(x>>16), byte(x>>8), byte(x)) } // File format description: http://www.microsoft.com/typography/otspec/otff.htm write32(0x00010000) // version 1.0 write16(uint16(len(tags))) // numTables write16(0) // searchRange write16(0) // entrySelector write16(0) // rangeShift // Table tags, includes offsets into following data segments. offset := uint32(12 + 16*len(tags)) // offset starts after table tags for i, tag := range tags { write32(tag) write32(0) write32(offset) write32(dataLens[i]) offset += dataLens[i] } // Data segments. for i, dataRef := range dataRefs { data := (*[1<<31 - 2]byte)((unsafe.Pointer)(C.CFDataGetBytePtr(dataRef)))[:dataLens[i]] buf = append(buf, data...) C.CFRelease(C.CFTypeRef(dataRef)) } return buf }
func (k *keychain) Remove(key string) error { if _, err := os.Stat(k.Path); os.IsNotExist(err) { return ErrKeyNotFound } serviceRef, err := _UTF8StringToCFString(k.Service) if err != nil { return err } defer C.CFRelease(C.CFTypeRef(serviceRef)) accountRef, err := _UTF8StringToCFString(key) if err != nil { return err } defer C.CFRelease(C.CFTypeRef(serviceRef)) query := map[C.CFTypeRef]C.CFTypeRef{ C.CFTypeRef(C.kSecClass): C.CFTypeRef(C.kSecClassGenericPassword), C.CFTypeRef(C.kSecAttrService): C.CFTypeRef(serviceRef), C.CFTypeRef(C.kSecAttrAccount): C.CFTypeRef(accountRef), C.CFTypeRef(C.kSecMatchLimit): C.CFTypeRef(C.kSecMatchLimitOne), } kref, err := openKeychain(k.Path) if err != nil { return err } searchArray := arrayToCFArray([]C.CFTypeRef{C.CFTypeRef(kref)}) defer C.CFRelease(C.CFTypeRef(searchArray)) query[C.CFTypeRef(C.kSecMatchSearchList)] = C.CFTypeRef(searchArray) queryDict := mapToCFDictionary(query) defer C.CFRelease(C.CFTypeRef(queryDict)) log.Printf("Removing keychain item service=%q, account=%q from osx keychain %q", k.Service, key, k.Path) return newKeychainError(C.SecItemDelete(queryDict)) }
func initDefaultRoots() { roots := x509.NewCertPool() var data C.CFDataRef = nil err := C.FetchPEMRoots(&data) if err != -1 { defer C.CFRelease(C.CFTypeRef(data)) buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data))) roots.AppendCertsFromPEM(buf) } varDefaultRoots = roots }
// Start listening to an event stream. func (es *EventStream) Start() { cPaths := C.ArrayCreateMutable(C.int(len(es.Paths))) defer C.CFRelease(C.CFTypeRef(cPaths)) for _, p := range es.Paths { p, _ = filepath.Abs(p) cpath := C.CString(p) defer C.free(unsafe.Pointer(cpath)) str := C.CFStringCreateWithCString(nil, cpath, C.kCFStringEncodingUTF8) C.CFArrayAppendValue(cPaths, unsafe.Pointer(str)) } since := C.FSEventStreamEventId(EventIDSinceNow) if es.Resume { since = C.FSEventStreamEventId(es.EventID) } if es.Events == nil { es.Events = make(chan []Event) } es.registryID = registry.Add(es) context := C.FSEventStreamContext{} info := C.uintptr_t(es.registryID) latency := C.CFTimeInterval(float64(es.Latency) / float64(time.Second)) if es.Device != 0 { es.stream = C.EventStreamCreateRelativeToDevice(&context, info, C.dev_t(es.Device), cPaths, since, latency, C.FSEventStreamCreateFlags(es.Flags)) } else { es.stream = C.EventStreamCreate(&context, info, cPaths, since, latency, C.FSEventStreamCreateFlags(es.Flags)) } started := make(chan struct{}) go func() { runtime.LockOSThread() es.rlref = C.CFRunLoopGetCurrent() C.FSEventStreamScheduleWithRunLoop(es.stream, es.rlref, C.kCFRunLoopDefaultMode) C.FSEventStreamStart(es.stream) close(started) C.CFRunLoopRun() }() if !es.hasFinalizer { runtime.SetFinalizer(es, finalizer) es.hasFinalizer = true } <-started }
func (dev *osxDevice) Close() { if !dev.disconnected { C.IOHIDDeviceClose(dev.osDevice, C.kIOHIDOptionsTypeSeizeDevice) dev.disconnected = true } if dev.osDevice != nil { C.CFRelease(C.CFTypeRef(dev.osDevice)) dev.osDevice = nil } if dev.closeDM != nil { dev.closeDM() dev.closeDM = nil } }
func initSystemRoots() { roots := NewCertPool() var data C.CFDataRef = nil err := C.ZToolsFetchPEMRoots(&data) if err == -1 { return } defer C.CFRelease(C.CFTypeRef(data)) buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data))) roots.AppendCertsFromPEM(buf) systemRoots = roots }
// The returned SecAccessRef, if non-nil, must be released via CFRelease. func createAccess(label string, trustedApplications []string) (C.CFTypeRef, error) { if len(trustedApplications) == 0 { return nil, nil } // Always prepend with empty string which signifies that we // include a NULL application, which means ourselves. trustedApplications = append([]string{""}, trustedApplications...) var err error var labelRef C.CFStringRef if labelRef, err = StringToCFString(label); err != nil { return nil, err } defer C.CFRelease(C.CFTypeRef(labelRef)) var trustedApplicationsRefs []C.CFTypeRef for _, trustedApplication := range trustedApplications { trustedApplicationRef, err := createTrustedApplication(trustedApplication) if err != nil { return nil, err } defer C.CFRelease(C.CFTypeRef(trustedApplicationRef)) trustedApplicationsRefs = append(trustedApplicationsRefs, trustedApplicationRef) } var access C.SecAccessRef trustedApplicationsArray := ArrayToCFArray(trustedApplicationsRefs) defer C.CFRelease(C.CFTypeRef(trustedApplicationsArray)) errCode := C.SecAccessCreate(labelRef, trustedApplicationsArray, &access) err = checkError(errCode) if err != nil { return nil, err } return C.CFTypeRef(access), nil }