/*! Copies an iSCSI discovery record object to a dictionary representation. * @param auth an iSCSI discovery record object. * @return a dictionary representation of the discovery record object or * NULL if the discovery record object is invalid. */ CFDictionaryRef iSCSIDiscoveryRecCreateDictionary(iSCSIDiscoveryRecRef discoveryRec) { return (CFDictionaryRef)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)discoveryRec, kCFPropertyListImmutable); }
static CFDictionaryRef copyXMLDomainDictionary(CFTypeRef context, void *xmlDomain) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; CFDictionaryRef result; __CFLock(&domain->_lock); if(!domain->_domainDict) { _loadXMLDomainIfStale((CFURLRef)context, domain); } result = (CFDictionaryRef)CFPropertyListCreateDeepCopy(__CFPreferencesAllocator(), domain->_domainDict, kCFPropertyListImmutable); __CFUnlock(&domain->_lock); return result; }
static void writeXMLValue(CFTypeRef context, void *xmlDomain, CFStringRef key, CFTypeRef value) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; const void *existing = NULL; __CFLock(&domain->_lock); if (domain->_domainDict == NULL) { _loadXMLDomainIfStale((CFURLRef )context, domain); } // check to see if the value is the same // if (1) the key is present AND value is !NULL and equal to existing, do nothing, or // if (2) the key is not present AND value is NULL, do nothing // these things are no-ops, and should not dirty the domain if (CFDictionaryGetValueIfPresent(domain->_domainDict, key, &existing)) { if (NULL != value && (existing == value || CFEqual(existing, value))) { __CFUnlock(&domain->_lock); return; } } else { if (NULL == value) { __CFUnlock(&domain->_lock); return; } } // We must append first so key gets another retain (in case we're // about to remove it from the dictionary, and that's the sole reference) // This should be a set not an array. if (!CFArrayContainsValue(domain->_dirtyKeys, CFRangeMake(0, CFArrayGetCount(domain->_dirtyKeys)), key)) { CFArrayAppendValue(domain->_dirtyKeys, key); } if (value) { // Must copy for two reasons - we don't want mutable objects in the cache, and we don't want objects allocated from a different allocator in the cache. CFTypeRef newValue = CFPropertyListCreateDeepCopy(__CFPreferencesAllocator(), value, kCFPropertyListImmutable); CFDictionarySetValue(domain->_domainDict, key, newValue); CFRelease(newValue); } else { CFDictionaryRemoveValue(domain->_domainDict, key); } __CFUnlock(&domain->_lock); }
static CFDictionaryRef copyVolatileDomainDictionary(CFTypeRef context, void *volatileDomain) { CFMutableDictionaryRef dict = (CFMutableDictionaryRef)volatileDomain; CFDictionaryRef result = (CFDictionaryRef)CFPropertyListCreateDeepCopy(__CFPreferencesAllocator(), dict, kCFPropertyListImmutable); return result; }
static void _copyAddlDataForType(CFAllocatorRef alloc, CFXMLNodeTypeCode xmlType, const void *src, void *dest) { switch(xmlType) { case kCFXMLNodeTypeDocument: { CFXMLDocumentInfo *srcData = (CFXMLDocumentInfo *)src; CFXMLDocumentInfo *destData = (CFXMLDocumentInfo *)dest; destData->sourceURL = srcData->sourceURL ? (CFURLRef)CFRetain(srcData->sourceURL) : NULL; destData->encoding = srcData->encoding; break; } case kCFXMLNodeTypeElement: { CFXMLElementInfo *srcData = (CFXMLElementInfo *)src; CFXMLElementInfo *destData = (CFXMLElementInfo *)dest; if (srcData->attributes && CFDictionaryGetCount(srcData->attributes) != 0) { destData->attributes = (CFDictionaryRef)CFPropertyListCreateDeepCopy(alloc, srcData->attributes, kCFPropertyListImmutable); destData->attributeOrder = (CFArrayRef)CFPropertyListCreateDeepCopy(alloc, srcData->attributeOrder, kCFPropertyListImmutable); } else { destData->attributes = NULL; destData->attributeOrder = NULL; } destData->isEmpty = srcData->isEmpty; break; } case kCFXMLNodeTypeProcessingInstruction: { CFXMLProcessingInstructionInfo *srcData = (CFXMLProcessingInstructionInfo *)src; CFXMLProcessingInstructionInfo *destData = (CFXMLProcessingInstructionInfo *)dest; destData->dataString = srcData->dataString ? (CFStringRef)CFStringCreateCopy(alloc, srcData->dataString) : NULL; break; } case kCFXMLNodeTypeEntity: { CFXMLEntityInfo *sourceData = (CFXMLEntityInfo *)src; CFXMLEntityInfo *destData = (CFXMLEntityInfo *)dest; destData->entityType = sourceData->entityType; destData->replacementText = sourceData->replacementText ? (CFStringRef)CFStringCreateCopy(alloc, sourceData->replacementText) : NULL; destData->entityID.systemID = sourceData->entityID.systemID ? (CFURLRef)CFRetain(sourceData->entityID.systemID) : NULL; destData->entityID.publicID = sourceData->entityID.publicID ? (CFStringRef)CFStringCreateCopy(alloc, sourceData->entityID.publicID) : NULL; destData->notationName = sourceData->notationName ? (CFStringRef)CFStringCreateCopy(alloc, sourceData->notationName) : NULL; break; } case kCFXMLNodeTypeEntityReference: { CFXMLEntityReferenceInfo *srcData = (CFXMLEntityReferenceInfo *)src; CFXMLEntityReferenceInfo *destData = (CFXMLEntityReferenceInfo *)dest; destData->entityType = srcData->entityType; break; } case kCFXMLNodeTypeDocumentType: case kCFXMLNodeTypeNotation: { // We can get away with this because the structures of CFXMLNotationInfo and CFXMLDocumentTypeInfo match. -- REW, 3/8/2000 CFXMLNotationInfo *srcData = (CFXMLNotationInfo *)src; CFXMLNotationInfo *destData = (CFXMLNotationInfo *)dest; destData->externalID.systemID = srcData->externalID.systemID ? (CFURLRef)CFRetain(srcData->externalID.systemID) : NULL; destData->externalID.publicID = srcData->externalID.publicID ? (CFStringRef)CFStringCreateCopy(alloc, srcData->externalID.publicID) : NULL; break; } case kCFXMLNodeTypeElementTypeDeclaration: { CFXMLElementTypeDeclarationInfo *srcData = (CFXMLElementTypeDeclarationInfo *)src; CFXMLElementTypeDeclarationInfo *destData = (CFXMLElementTypeDeclarationInfo *)dest; destData->contentDescription = srcData->contentDescription ? (CFStringRef)CFStringCreateCopy(alloc, srcData->contentDescription) : NULL; break; } case kCFXMLNodeTypeAttributeListDeclaration: { CFXMLAttributeListDeclarationInfo *sourceData = (CFXMLAttributeListDeclarationInfo *)src; CFXMLAttributeListDeclarationInfo *destData = (CFXMLAttributeListDeclarationInfo *)dest; CFIndex idx; destData->numberOfAttributes = sourceData->numberOfAttributes; destData->attributes = sourceData->numberOfAttributes ? (CFXMLAttributeDeclarationInfo *)CFAllocatorAllocate(alloc, sizeof(CFXMLAttributeDeclarationInfo)*sourceData->numberOfAttributes, 0) : NULL; for (idx = 0; idx < sourceData->numberOfAttributes; idx ++) { CFXMLAttributeDeclarationInfo sourceAttr = sourceData->attributes[idx]; CFXMLAttributeDeclarationInfo *destAttr = &(destData->attributes[idx]); destAttr->attributeName = (CFStringRef)CFStringCreateCopy(alloc, sourceAttr.attributeName); destAttr->typeString = (CFStringRef)CFStringCreateCopy(alloc, sourceAttr.typeString); destAttr->defaultString = (CFStringRef)CFStringCreateCopy(alloc, sourceAttr.defaultString); } break; } default: CFAssert2(false, __kCFLogAssertion, "%s(): Encountered unexpected typeID %d (additionalData should be empty)", __PRETTY_FUNCTION__, xmlType); } }
/*! Creates a mutable connection configuration object from an existing one. */ iSCSIMutableConnectionConfigRef iSCSIConnectionConfigCreateMutableWithExisting(iSCSIConnectionConfigRef config) { return (iSCSIMutableConnectionConfigRef)CFPropertyListCreateDeepCopy( kCFAllocatorDefault,config,kCFPropertyListMutableContainersAndLeaves); }
/*! Creates a new discovery record object from a dictionary representation. * @return an iSCSI discovery object or NULL if object creation failed. */ iSCSIDiscoveryRecRef iSCSIDiscoveryRecCreateWithDictionary(CFDictionaryRef dict) { return CFPropertyListCreateDeepCopy(kCFAllocatorDefault,dict,kCFPropertyListImmutable); }
/** * Return a copy of passed node and it's children * * @param node the plist to copy * @return copied plist */ plist_t plist_copy(plist_t node) { return CFPropertyListCreateDeepCopy(kCFAllocatorDefault, node, kCFPropertyListMutableContainers); }
static void LeakTest(TestFunc tester) // Given a test name and a pointer to a test function, // this routine calls the test function repeatedly to check // for SCF preferences reference count leaks. { OSStatus err; SCPreferencesRef prefsRef; CFArrayRef allKeys; int i; SInt32 startCount; SInt32 endCount; // This is kinda cheesy. We need to use the same SCPreferencesRef // that MoreSCF uses because otherwise we can't see the reference // count changes done by MoreSCF. Ideally, we wouldn't want to run // within a MoreSCOpen/MoreSCClose pair because then our changes // aren't necessarily being committed to the database. However, // given the current MoreSCF architecture, where the SCPreferenceRef // is only valid inside the MoreSCOpen/MoreSCClose pair, that's // exactly what we have to do. allKeys = NULL; err = MoreSCOpen(false, false); if (err == noErr) { prefsRef = MoreSCGetSCPreferencesRef(); } // Now get a copy of the array of all keys in the database. // We make this copy using CFPropertyListCreateDeepCopy so we // know that it's completely independent of the SCF. if (err == noErr) { CFArrayRef allKeysOrig; allKeysOrig = NULL; allKeysOrig = SCPreferencesCopyKeyList(prefsRef); if (allKeysOrig == NULL) { err = SCError(); } if (err == noErr) { allKeys = (CFArrayRef) CFPropertyListCreateDeepCopy(NULL, allKeysOrig, kCFPropertyListMutableContainersAndLeaves); // C++ requires cast if (allKeys == NULL) { err = coreFoundationUnknownErr; } } CFQRelease(allKeysOrig); } // Now do the reference counting test. Call the tester function // a few times to allow the refcounts to stabilise. Then get // a summ of all the nodes in all of the keys in SCF. Then // run the test a 10 more times and get another count. If // the counts are different, we're in trouble. if (err == noErr) { for (i = 0; i < 3; i++) { tester(); } startCount = TotalAllRefCounts(prefsRef, allKeys); for (i = 0; i < 10; i++) { tester(); } endCount = TotalAllRefCounts(prefsRef, allKeys); if (startCount != endCount) { CFIndex keyCount; CFIndex keyIndex; fprintf(stderr, "*** Leaked %ld reference counts.\n", endCount - startCount); keyCount = CFArrayGetCount(allKeys); for (keyIndex = 0; keyIndex < keyCount; keyIndex++) { CFPropertyListRef thisPref; // The commented out code is only needed when you're actively // trying to track down a leak. Given that leaks are rare // I decided against making a proper architecture for this. // Just uncomment the code and modify it appropriately. startCount = 0; thisPref = SCPreferencesGetValue(prefsRef, (CFStringRef) CFArrayGetValueAtIndex(allKeys, keyIndex)); // C++ requires cast CFQPropertyListDeepApplyFunction(thisPref, RefCounter, (void *) &startCount ); // if (keyIndex == 0) { // fprintf(stderr, "*** BEFORE ***\n"); // PrintPropertyList(thisPref); // } tester(); endCount = 0; thisPref = SCPreferencesGetValue(prefsRef, (CFStringRef) CFArrayGetValueAtIndex(allKeys, keyIndex)); // C++ requires cast CFQPropertyListDeepApplyFunction(thisPref, RefCounter, (void *) &endCount ); // if (keyIndex == 0) { // fprintf(stderr, "*** AFTER ***\n"); // PrintPropertyList(thisPref); // } if (startCount != endCount) { fprintf(stderr, "*** Leaked %ld reference counts in set number %ld\n", endCount - startCount, keyIndex); CFShow(CFArrayGetValueAtIndex(allKeys, keyIndex)); } } } } MoreSCClose(&err, false); CFQRelease(allKeys); if (err != noErr) { fprintf(stderr, "*** Failed with error %ld!\n", err); } }