NSDataWritingFileProtectionComplete in OS X - objective-c

Looking the documentation:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html
I see that NSDataWritingFileProtectionComplete is "Available in OS X v10.8 and later" but when I try to use it in my code I have a compilation error. Checking the NSData header I see that this feature is only available in iOS:
NSDataWritingFileProtectionComplete NS_ENUM_AVAILABLE_IOS(4_0)
I'm making something wrong or the documentation is incorrect?

Looking at the enums as defined in the MacOS 10.8 SDK, I see:
typedef NS_OPTIONS(NSUInteger, NSDataWritingOptions) {
NSDataWritingAtomic = 1UL << 0, // Hint to use auxiliary file when saving; equivalent to atomically:YES
NSDataWritingWithoutOverwriting NS_ENUM_AVAILABLE(10_8, 6_0) = 1UL << 1, // Hint to return prevent overwriting an existing file. Cannot be combined with NSDataWritingAtomic.
NSDataWritingFileProtectionNone NS_ENUM_AVAILABLE_IOS(4_0) = 0x10000000,
NSDataWritingFileProtectionComplete NS_ENUM_AVAILABLE_IOS(4_0) = 0x20000000,
"NS_ENUM_AVAILABLE_IOS" is a macro that expands to
#define NS_ENUM_AVAILABLE_IOS(_ios) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios)
The "__MAC_NA" bit means "not applicable", which means that the documentation is currently wrong. This functionality is only available in iOS.
You should file a documentation bug with Apple about this.

Related

macOS deprecated APIs

The company I work for has developed a program and the last time the code was touched was 2 years ago. Now the program needs to become notarized so I was asked to take care of the program.
I ported the code to latest Xcode (10.2.1) and latest macOS. But Xcode warns me about the deprecation of a few API calls:
/Users/rowelz/Documents/Develop/Code/ThinPrint/in GIT/myProject/osx-client/src/com.myProject.bootstrap/EZPBootstrapper.m:116:51: 'SMJobCopyDictionary' is deprecated: first deprecated in macOS 10.10
NSDictionary *plist = (__bridge NSDictionary *) SMJobCopyDictionary(
kSMDomainSystemLaunchd, (__bridge CFStringRef) (label));
/Users/rowelz/Documents/Develop/Code/ThinPrint/in GIT/myProject/osx-client/src/com.myProject.bootstrap/EZPBootstrapper.m:193:21: 'SMJobRemove' is deprecated: first deprecated in macOS 10.10
result = (BOOL) SMJobRemove(kSMDomainSystemLaunchd,
(__bridge CFStringRef) label, self->_authRef, FALSE, &cfError);
/Users/rowelz/Documents/Develop/Code/ThinPrint/in GIT/myProject/osx-client/src/com.myProject.bootstrap/EZPAppDelegate.m:193:15: 'SMJobSubmit' is deprecated: first deprecated in macOS 10.10
submitted = SMJobSubmit(kSMDomainUserLaunchd, (__bridge CFDictionaryRef)(plist), NULL, &cfError);
/Users/rowelz/Documents/Develop/Code/ThinPrint/in GIT/ezeep/osx-client/src/com.myProject.bootstrap/EZPAppDelegate.m:214:13: 'SMJobRemove' is deprecated: first deprecated in macOS 10.10
removed = SMJobRemove(kSMDomainUserLaunchd, (__bridge CFStringRef)kEzeepServiceNameUpdaterBstrap, NULL, false, NULL);
My Supervisor in this project gave the following boundary conditions:
Program should work during the next one year only. After that It will be replaced by another program of our house.
During this year it should work without limitations, crashes and so on.
I would prefer not to make any changes to the code, since the warnings regarding SMJobCopyDictionary, SMJobRemove and SMJobSubmit means that there is a big change to do - the whole program has to be written anew. And this would be a big effort for a one year life-span.
My Question:
I would like to write a little tool that checks for the availability of these API calls. I will then execute this tool on every beta of macOS until the final release of macOS 10.15. Of course if that tool shows a problem I will then rewrite the "now defective" program.
Would that be sufficient to detect a problem with the existence of the API? And what function can I use to detect the availability without actually calling them trying to install a launchd binary? I guess the above APIs are CoreFoundation ?
Thanks in advance for you help.
I found this here at stack overflow and it seems to work:
#include <dlfcn.h>
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
BOOL notFound = NO;
void *lib = dlopen("/System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement", RTLD_LAZY);
if(lib == NULL)
{
printf("Library not found. (/System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement).\n");
exit(1);
}
void *function1 = dlsym(lib, "SMJobCopyDictionary");
if(function1 == NULL)
{
printf("Function not found: SMJobCopyDictionary\n");
notFound = YES;
}
// .... and so on
dlclose(lib);
if(notFound)
{
exit(1);
}
printf("Ok, all functions found.\n");
}
return 0;
}
will that be sufficient to show a call to a deprecated and removed API?
This is speculation, but I feel confident in it: Apple will not remove these APIs from 10.15. Deprecating APIs is done regularly, but actually removing them breaks existing applications and is done very rarely.
It is possible (though unlikely I think) that they will remove the headers from the 10.15 SDK, in which case you will need to keep building against the 10.14 SDK (using Xcode 10).
And if the 10.15 SDK still contains the headers, the situation is the same as it is now and you won't have any problems.

Cocoa check if function exists

I'd like to use a function that's only available on OS X 10.9, but WITHOUT compiling with the 10.9 SDK. Is that possible?
I've tried weak linking, but the compiler just gives out an error that the function is not defined.
You say you don't want to compile against 10.9, but give no reason. Just in case you can:
If you set your target to 10.9 and your deployment to something lower then Xcode will weak link the 10.9 frameworks. You can then test for a C function being available by comparing its name to NULL. This fragment is taken from this document:
extern int MyWeakLinkedFunction() __attribute__((weak_import));
int main()
{
int result = 0;
if (MyWeakLinkedFunction != NULL)
{
result = MyWeakLinkedFunction();
}
return result;
}
(BTW: no sandbox issues this way.)
Assuming you are talking about a C function, you can do this with the dlopen function:
#include <dlfcn.h>
int main() {
void *lib = dlopen("/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices", RTLD_LAZY);
void *function = dlsym(lib, "CGColorGetConstantColor");
// cast the function to the right format
CGColorRef (*dynamic_getConstantColor)(CFStringRef colorName) = function;
NSLog(#"%#", dynamic_getConstantColor(CFSTR("kCGColorBlack")));
dlclose(lib);
}
Output:
2013-06-20 12:43:13.510 TestProj[1699:303] [ (kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Generic Gray Profile)] ( 0 1 )
You will need to figure out the dylib in which the function you want resides, first, though.
This will break the sandbox limitations on iOS, and Mac most likely as well. It is the price you pay for trying to get around the linker.
If you are dealing with Objective-C methods, maybe you could do it with selectors..
So first check if the selector is available with:
[object respondsToSelector:#selector(osxMavericksFun)]
And if this test is correct try firing the Method via selectors
[object performSelector:#selector(osxMavericksFun)];
If you want to call c functions there is no way to do this.
You should do it like this
if (AXIsProcessTrustedWithOptions != NULL){
NSDictionary *options = #{(__bridge id)kAXTrustedCheckOptionPrompt: #YES};
accessibilityEnabled = AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef)options);
}else{
accessibilityEnabled = AXIsProcessTrusted();
}
This method is described in apple's documentation Listing 3-2. It is much simpler than the method described by Richard J. Ross III which you accepted as correct.

File copy with progress indicator [duplicate]

FSCopyObjectAsync is Deprecated in OS X v10.8, Now how to display progress indictor for file copy operation.
My answer assumes you're talking about showing the progress of a single file being copied.
Yes, "FSCopyObjectAsync" been deprecated but it's not gone yet.
And as you have discovered, Apple has not yet provided a useful replacement for the functionality that will eventually be removed. I suspect (but do not know for certain) that when the new functionality comes in, perhaps for 10.9, it will be delivered in the "NSFileManagerDelegate" protocol for delegates to make use of.
To make certain of that, Apple needs to be aware there are lots of developers need this. File a bug report at http://bugreporter.apple.com -- it'll likely be closed as a duplicate, but every vote counts.
copyfile(3) is alternative for FSCopyObjectAsync. Here is example of copyfile(3) with Progress Callback.
I created an open source project addressing this issue, I wrapped copy file(3) on a NSOperation and created a gui for it, please check it out and maybe contribute to make it better.
https://github.com/larod/FileCopyDemo
Coping files with progressIndicator in C
#define BUFSIZE (64*1024)
void *thread_proc(void *arg);
{
//outPath & inPatn an NSString paths
char buffer[BUFSIZE];
const char * outputFile = [outPath UTF8String];
const char * inputFile = [inPath UTF8String];
int in = open(inputFile, O_RDONLY);
int out = open(outputFile, O_WRONLY | O_CREAT | O_TRUNC);
vvolatile off_t progress;
progress = 0;
ssize_t bytes_read;
double fileSize = 0;
NSNumber * theSize;
if ([inPath getResourceValue:&theSize forKey:NSURLFileSizeKey error:nil])
fileSize = [theSize doubleValue];
[progressIndicator setMaxValue:fileSize];
while((bytes_read = read(in, buffer, BUFSIZE)) > 0)
{
write(out, buffer, BUFSIZE);
progress += bytes_read;
[progressIndicator setDoubleValue:progress];
}
// copy is done, or an error occurred
close(in);
close(out);
}

About stl list::splice

I am facing a problem with splicing the list with itself. Note that I have gone through splice() on std::list and iterator invalidation
There the question was about two different lists. But my question is about the same list.
mylist.splice(mylist.end(), mylist, ++mylist.begin());
It seems that gcc 3.x is invalidating the moved iterator. So I suppose it is deallocating and allocating the node again. This does not make sense for the same list. SGI does tell that this version of splice should not invalidate any iterators. Is this a bug with gcc 3.x, if it is there any workaround?
In the mean time I was going through the stl_list.h file. But stuck with the transfer() function, I could not find a definition for these.
struct _List_node_base
{
_List_node_base* _M_next; ///< Self-explanatory
_List_node_base* _M_prev; ///< Self-explanatory
static void
swap(_List_node_base& __x, _List_node_base& __y);
void
transfer(_List_node_base * const __first,
_List_node_base * const __last);
void
reverse();
void
hook(_List_node_base * const __position);
void
unhook();
};
Do you have any idea where can I look for these function definitions?
This functions are in the libstdc++ sources, not the headers. In 3.4 it's in libstdc++-v3/src/list.cc
http://gcc.gnu.org/viewcvs/branches/gcc-3_4-branch/libstdc%2B%2B-v3/src/list.cc?view=markup
Have you tried compiling with -D_GLIBCXX_DEBUG ? That will enable the Debug Mode and tell you if you're using invalid iterators or anything else that causes the problem.
I just tried this simple test with GCC 3.4, with and without debug mode, and it worked fine:
#include <list>
#include <iostream>
#include <string>
int main()
{
std::list<std::string> l;
l.push_back("1");
l.push_back("2");
l.push_back("3");
l.push_back("4");
l.push_back("5");
l.push_back("6");
l.splice(l.end(), l, ++l.begin());
for (std::list<std::string>::iterator i = l.begin(), e = l.end(); i != e; ++i)
std::cout << *i << ' ';
std::cout << std::endl;
}
Modifying it further and debugging it I see that no element is destroyed and reallocated when doing the splice, so I suspect the bug is in your program. It's hard to know, as you haven't actually said what the problem is.

Symbian: kern-exec 3 panic on RLibrary::Load

I have troubles with dynamic loading of libraries - my code panics with Kern-Exec 3. The code is as follows:
TFileName dllName = _L("mydll.dll");
TFileName dllPath = _L("c:\\sys\\bin\\");
RLibrary dll;
TInt res = dll.Load(dllName, dllPath); // Kern-Exec 3!
TLibraryFunction f = dll.Lookup(1);
if (f)
f();
I receive panic on TInt res = dll.Load(dllName, dllPath); What can I do to get rid of this panic? mydll.dll is really my dll, which has only 1 exported function (for test purposes). Maybe something wrong with the DLL? Here's what it is:
def file:
EXPORTS
_ZN4Init4InitEv # 1 NONAME
pkg file:
#{"mydll DLL"},(0xED3F400D),1,0,0
;Localised Vendor name
%{"Vendor-EN"}
;Unique Vendor name
:"Vendor"
"$(EPOCROOT)Epoc32\release\$(PLATFORM)\$(TARGET)\mydll.dll"-"!:\sys\bin\mydll.dll"
mmp file:
TARGET mydll.dll
TARGETTYPE dll
UID 0x1000008d 0xED3F400D
USERINCLUDE ..\inc
SYSTEMINCLUDE \epoc32\include
SOURCEPATH ..\src
SOURCE mydllDllMain.cpp
LIBRARY euser.lib
#ifdef ENABLE_ABIV2_MODE
DEBUGGABLE_UDEBONLY
#endif
EPOCALLOWDLLDATA
CAPABILITY CommDD LocalServices Location MultimediaDD NetworkControl NetworkServices PowerMgmt ProtServ ReadDeviceData ReadUserData SurroundingsDD SwEvent TrustedUI UserEnvironment WriteDeviceData WriteUserData
source code:
// Exported Functions
namespace Init
{
EXPORT_C TInt Init()
{
// no implementation required
return 0;
}
}
header file:
#ifndef __MYDLL_H__
#define __MYDLL_H__
// Include Files
namespace Init
{
IMPORT_C TInt Init();
}
#endif // __MYDLL_H__
I have no ideas about this... Any help is greatly appreciated.
P.S. I'm trying to do RLibrary::Load because I have troubles with static linkage. When I do static linkage, my main program doesn't start at all. I decided to check what happens and discovered this issue with RLibrary::Load.
A KERN-EXEC 3 panic is caused by an unhandled exception (CPU fault) generated by trying to invalidly access a region of memory. This invalid memory access can be for both code (for example, bad PC by stack corruption) or data (for example, accessing freed memory). As such these are typically observed when dereferencing a NULL pointer (it is equivalent to a segfault).
Certainly the call to RLibrary::Load should never raise a KERN-EXEC 3 due to programmatic error, it is likely to be an environmental issue. As such I have to speculate on what is happening.
I believe the issue that is observed is due to stack overflow. Your MMP file does not specify the stack or heap size the initial thread should use. As such the default of 4Kb (if I remember correctly) will be used. Equally you are using TFileName - use of these on the stack is generally not recommended to avoid... stack overflow.
You would be better off using the _LIT() macro instead - this will allow you to provide the RLibrary::Load function with a descriptor directly referencing the constant strings as located in the constant data section of the binary.
As a side note, you should check the error value to determine the success of the function call.
_LIT(KMyDllName, "mydll.dll");
_LIT(KMyDllPath, "c:\\sys\\bin\\");
RLibrary dll;
TInt res = dll.Load(KMyDllName, MyDllPath); // Hopefully no Kern-Exec 3!
if(err == KErrNone)
{
TLibraryFunction f = dll.Lookup(1);
if (f)
f();
}
// else handle error
The case that you can't use static linkage should be a strong warning to you. It shows that there is something wrong with your DLL and using dynamic linking won't change anything.
Usually in these cases the problem is in mismatched capabilities. DLL must have at least the same set of capabilities that your main program has. And all those capabilities should be covered by your developer cert.