Get the boot time in objective c - objective-c

how can i get the boot time of ios in objective c ?
Is there a way to get it?

Don't know if this will work in iOS, but in OS X (which is essentially the same OS) you would use sysctl(). This is how the OS X Unix utility uptime does it. Source code is available - search for "boottime".
#include <sys/types.h>
#include <sys/sysctl.h>
// ....
#define MIB_SIZE 2
int mib[MIB_SIZE];
size_t size;
struct timeval boottime;
mib[0] = CTL_KERN;
mib[1] = KERN_BOOTTIME;
size = sizeof(boottime);
if (sysctl(mib, MIB_SIZE, &boottime, &size, NULL, 0) != -1)
{
// successful call
NSDate* bootDate = [NSDate dateWithTimeIntervalSince1970:boottime.tv_sec];
}
The restricted nature of programming in the iOS sandboxed environment might make it not work, I don't know, I haven't tried it.

I took JeremyP's answer, gave the result the full microsecond precision, clarified the names of local variables, improved the order, and put it into a method:
#include <sys/types.h>
#include <sys/sysctl.h>
// ....
+ (nullable NSDate *)bootDate
{
// nameIntArray and nameIntArrayLen
int nameIntArrayLen = 2;
int nameIntArray[nameIntArrayLen];
nameIntArray[0] = CTL_KERN;
nameIntArray[1] = KERN_BOOTTIME;
// boot_timeval
struct timeval boot_timeval;
size_t boot_timeval_size = sizeof(boot_timeval);
if (sysctl(nameIntArray, nameIntArrayLen, &boot_timeval, &boot_timeval_size, NULL, 0) == -1)
{
return nil;
}
// bootSince1970TimeInterval
NSTimeInterval bootSince1970TimeInterval = (NSTimeInterval)boot_timeval.tv_sec + ((NSTimeInterval)boot_timeval.tv_usec / 1000000);
// return
return [NSDate dateWithTimeIntervalSince1970:bootSince1970TimeInterval];
}

Related

Apportable gives compile error "arithmetic on a pointer to an incomplete type"

Apportable error
arithmetic on a pointer to an incomplete type 'struct if_msghdr'
socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);
Here is the code. The code is working fine on ios/xcode but gives above error to interfaceMsgStruct with apportable. I have get this code from google and it is widely used so i dont think the code might have error. If it does then please correct me.
#import "MFMacAddress.h"
#implementation MFMacAddress
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
+ (NSString *)getMacAddress
{
int mgmtInfoBase[6];
char *msgBuffer = NULL;
size_t length;
unsigned char macAddress[6];
struct if_msghdr *interfaceMsgStruct;
struct sockaddr_dl *socketStruct;
NSString *errorFlag = NULL;
// Setup the management Information Base (mib)
mgmtInfoBase[0] = CTL_NET; // Request network subsystem
mgmtInfoBase[1] = AF_ROUTE; // Routing table info
mgmtInfoBase[2] = 0;
mgmtInfoBase[3] = AF_LINK; // Request link layer information
mgmtInfoBase[4] = NET_RT_IFLIST; // Request all configured interfaces
// With all configured interfaces requested, get handle index
if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0)
errorFlag = #"if_nametoindex failure";
else
{
// Get the size of the data available (store in len)
if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0)
errorFlag = #"sysctl mgmtInfoBase failure";
else
{
// Alloc memory based on above call
if ((msgBuffer = malloc(length)) == NULL)
errorFlag = #"buffer allocation failure";
else
{
// Get system information, store in buffer
if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
errorFlag = #"sysctl msgBuffer failure";
}
}
}
// Befor going any further...
if (errorFlag != NULL)
{
NSLog(#"Error: %#", errorFlag);
return errorFlag;
}
// Map msgbuffer to interface message structure
interfaceMsgStruct = (struct if_msghdr *) msgBuffer;
// Map to link-level socket structure
socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);
// Copy link layer address data in socket structure to an array
memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);
// Read from char array into a string object, into traditional Mac address format
NSString *macAddressString = [NSString stringWithFormat:#"%02X:%02X:%02X:%02X:%02X:%02X",
macAddress[0], macAddress[1], macAddress[2],
macAddress[3], macAddress[4], macAddress[5]];
NSLog(#"Mac Address: %#", macAddressString);
// Release the buffer memory
free(msgBuffer);
return macAddressString;
}
#end
To get the mac address, you can do
[[UIDevice currentDevice] macAddress]
which returns an NSString *
The compile error you're seeing is the result of a different system headers between IOS and Android. We're working on a more transparent solution, but in the meantime the solution above is an easy workaround.
Often you get this error when the definition of struct if_msghdr is not 'visible'.
Check if you need to #include other header files, or if different conditional compilation options locked it out.

How to distinguish MacBook and Mac desktops programmatically?

I'm working on a Mac app that should distinguish MacBook and Mac desktops (iMac/Mac Pro).
I think I can get it done with model number. Then how I can get the model number? And which letter indicates it's a notebook or desktop? Or is there any other easier or better way?
You can use this little program. NSLog the output to test it.
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/sysctl.h>
+ (NSString *)machineModel
{
size_t length = 0;
sysctlbyname("hw.model", NULL, &length, NULL, 0);
if (length) {
char *m = malloc(length * sizeof(char));
sysctlbyname("hw.model", m, &length, NULL, 0);
NSString *model = [NSString stringWithUTF8String:m];
free(m);
return model;
}
return #"Unknown model";
}
It will provide the same output as entering sysctl hw.model on the terminal.
You haven't specified a language, but from Terminal sysctl hw.model will return with an identifier for the current Mac. For example, on my computer it returns MacBookPro5,5.

Get the precise time of system bootup on iOS/OS X

Is there an API to obtain the NSDate or NSTimeInterval representing the time the system booted? Some APIs such as [NSProcessInfo systemUptime] and Core Motion return time since boot. I need to precisely correlate these uptime values with NSDates, to about a millisecond.
Time since boot ostensibly provides more precision, but it's easy to see that NSDate already provides precision on the order of 100 nanoseconds, and anything under a microsecond is just measuring interrupt latency and PCB clock jitter.
The obvious thing is to subtract the uptime from the current time [NSDate date]. But that assumes that time does not change between the two system calls, which is, well, hard to accomplish. Moreover if the thread is preempted between the calls, everything is thrown off. The workaround is to repeat the process several times and use the smallest result, but yuck.
NSDate must have a master offset it uses to generate objects with the current time from the system uptime, is there really no way to obtain it?
In OSX you could use sysctl(). This is how the OSX Unix utility uptime does it. Source code is available - search for boottime.
Fair warning though, in iOS i have no idea if this would work.
UPDATE: found some code :)
#include <sys/types.h>
#include <sys/sysctl.h>
#define MIB_SIZE 2
int mib[MIB_SIZE];
size_t size;
struct timeval boottime;
mib[0] = CTL_KERN;
mib[1] = KERN_BOOTTIME;
size = sizeof(boottime);
if (sysctl(mib, MIB_SIZE, &boottime, &size, NULL, 0) != -1)
{
// successful call
NSDate* bootDate = [NSDate dateWithTimeIntervalSince1970:
boottime.tv_sec + boottime.tv_usec / 1.e6];
}
see if this works...
The accepted answer, using systcl, works, but the values returned by sysctl for KERN_BOOTTIME, at least in my testing (Darwin Kernel Version 11.4.2), are always in whole seconds (the microseconds field, tv_usec, is 0). This means the resulting time may be up to 1 second off, which is not very accurate.
Also, having compared that value, to one derived experimentally from the difference between the REALTIME_CLOCK and CALENDAR_CLOCK, they sometimes differ by a couple seconds, so its not clear whether the KERN_BOOTTIME value corresponds exactly to the time-basis for the uptime clocks.
There is another way. It could give result slightly different (less or more) than accepted answer
I have compared them. I get difference -7 second for OSX 10.9.3 and +2 second for iOS 7.1.1
As i understand this way gives same result if wall clock changed, but accepted answer gives different results if wall clock changed...
Here code:
static CFAbsoluteTime getKernelTaskStartTime(void) {
enum { MICROSECONDS_IN_SEC = 1000 * 1000 };
struct kinfo_proc info;
bzero(&info, sizeof(info));
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a specific process ID = 0.
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, 0};
// Call sysctl.
size_t size = sizeof(info);
const int sysctlResult = sysctl(mib, COUNT_ARRAY_ELEMS(mib), &info, &size, NULL, 0);
assert(0 != sysctlResult);
const struct timeval * timeVal = &(info.kp_proc.p_starttime);
NSTimeInterval result = -kCFAbsoluteTimeIntervalSince1970;
result += timeVal->tv_sec;
result += timeVal->tv_usec / (double)MICROSECONDS_IN_SEC;
return result;
}
Refer to this category
NSDate+BootTime.h
#import <Foundation/Foundation.h>
#interface NSDate (BootTime)
+ (NSDate *)bootTime;
+ (NSTimeInterval)bootTimeTimeIntervalSinceReferenceDate;
#end
NSDate+BootTime.m
#import "NSDate+BootTime.h"
#include <sys/types.h>
#include <sys/sysctl.h>
#implementation NSDate (BootTime)
+ (NSDate *)bootTime {
return [NSDate dateWithTimeIntervalSinceReferenceDate:[NSDate bootTimeTimeIntervalSinceReferenceDate]];
}
+ (NSTimeInterval)bootTimeTimeIntervalSinceReferenceDate {
return getKernelTaskStartTime();
}
////////////////////////////////////////////////////////////////////////
#pragma mark - Private
////////////////////////////////////////////////////////////////////////
#define COUNT_ARRAY_ELEMS(arr) sizeof(arr)/sizeof(arr[0])
static CFAbsoluteTime getKernelTaskStartTime(void) {
enum { MICROSECONDS_IN_SEC = 1000 * 1000 };
struct kinfo_proc info;
bzero(&info, sizeof(info));
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a specific process ID = 0.
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, 0};
// Call sysctl.
size_t size = sizeof(info);
const int sysctlResult = sysctl(mib, COUNT_ARRAY_ELEMS(mib), &info, &size, NULL, 0);
if (sysctlResult != -1) {
const struct timeval * timeVal = &(info.kp_proc.p_starttime);
NSTimeInterval result = -kCFAbsoluteTimeIntervalSince1970;
result += timeVal->tv_sec;
result += timeVal->tv_usec / (double)MICROSECONDS_IN_SEC;
return result;
}
return 0;
}
#end
The routines inside mach/mach_time.h are guaranteed to be monotonically increasing, unlike NSDate.

<CFData 0x100516c60 [0x7fff71adaea0]>{length = 6, capacity = 6, bytes = 0x0022412b03ad}

Every time I start build my Xcode Project, I get this in the console:
<CFData 0x100516c60 [0x7fff71adaea0]>{length = 6, capacity = 6, bytes = 0x0022412b03ad}
I have no idea, what it means and what it's causing it.
Can someone help me?
Thx!
Edit:
I think this method creates it:
//
// PrimaryMac.m
// Network Radar
//
// Created by Daniel Diener on 06.07.11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "PrimaryMac.h"
#include <stdio.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include "if_types.h"
#include "route.h"
#include "if_ether.h"
#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <paths.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IOEthernetController.h>
#implementation PrimaryMac
#synthesize localMac, remoteMac;
static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices);
static kern_return_t GetMACAddress(io_iterator_t intfIterator, UInt8 *MACAddress, UInt8 bufferSize);
- (id)init
{
self = [super init];
if (self) {
}
return self;
}
//LOCAL MAC:::::::::::::::::::
// Returns an iterator containing the primary (built-in) Ethernet interface. The caller is responsible for
// releasing the iterator after the caller is done with it.
static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices)
{
kern_return_t kernResult;
CFMutableDictionaryRef matchingDict;
CFMutableDictionaryRef propertyMatchDict;
// Ethernet interfaces are instances of class kIOEthernetInterfaceClass.
// IOServiceMatching is a convenience function to create a dictionary with the key kIOProviderClassKey and
// the specified value.
matchingDict = IOServiceMatching(kIOEthernetInterfaceClass);
// Note that another option here would be:
// matchingDict = IOBSDMatching("en0");
// but en0: isn't necessarily the primary interface, especially on systems with multiple Ethernet ports.
if (NULL == matchingDict) {
printf("IOServiceMatching returned a NULL dictionary.\n");
}
else {
// Each IONetworkInterface object has a Boolean property with the key kIOPrimaryInterface. Only the
// primary (built-in) interface has this property set to TRUE.
// IOServiceGetMatchingServices uses the default matching criteria defined by IOService. This considers
// only the following properties plus any family-specific matching in this order of precedence
// (see IOService::passiveMatch):
//
// kIOProviderClassKey (IOServiceMatching)
// kIONameMatchKey (IOServiceNameMatching)
// kIOPropertyMatchKey
// kIOPathMatchKey
// kIOMatchedServiceCountKey
// family-specific matching
// kIOBSDNameKey (IOBSDNameMatching)
// kIOLocationMatchKey
// The IONetworkingFamily does not define any family-specific matching. This means that in
// order to have IOServiceGetMatchingServices consider the kIOPrimaryInterface property, we must
// add that property to a separate dictionary and then add that to our matching dictionary
// specifying kIOPropertyMatchKey.
propertyMatchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (NULL == propertyMatchDict) {
printf("CFDictionaryCreateMutable returned a NULL dictionary.\n");
}
else {
// Set the value in the dictionary of the property with the given key, or add the key
// to the dictionary if it doesn't exist. This call retains the value object passed in.
CFDictionarySetValue(propertyMatchDict, CFSTR(kIOPrimaryInterface), kCFBooleanTrue);
// Now add the dictionary containing the matching value for kIOPrimaryInterface to our main
// matching dictionary. This call will retain propertyMatchDict, so we can release our reference
// on propertyMatchDict after adding it to matchingDict.
CFDictionarySetValue(matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
CFRelease(propertyMatchDict);
}
}
// IOServiceGetMatchingServices retains the returned iterator, so release the iterator when we're done with it.
// IOServiceGetMatchingServices also consumes a reference on the matching dictionary so we don't need to release
// the dictionary explicitly.
kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, matchingServices);
if (KERN_SUCCESS != kernResult) {
printf("IOServiceGetMatchingServices returned 0x%08x\n", kernResult);
}
return kernResult;
}
// Given an iterator across a set of Ethernet interfaces, return the MAC address of the last one.
// If no interfaces are found the MAC address is set to an empty string.
// In this sample the iterator should contain just the primary interface.
static kern_return_t GetMACAddress(io_iterator_t intfIterator, UInt8 *MACAddress, UInt8 bufferSize)
{
io_object_t intfService;
io_object_t controllerService;
kern_return_t kernResult = KERN_FAILURE;
// Make sure the caller provided enough buffer space. Protect against buffer overflow problems.
if (bufferSize < kIOEthernetAddressSize) {
return kernResult;
}
// Initialize the returned address
bzero(MACAddress, bufferSize);
// IOIteratorNext retains the returned object, so release it when we're done with it.
while ((intfService = IOIteratorNext(intfIterator)))
{
CFTypeRef MACAddressAsCFData;
// IONetworkControllers can't be found directly by the IOServiceGetMatchingServices call,
// since they are hardware nubs and do not participate in driver matching. In other words,
// registerService() is never called on them. So we've found the IONetworkInterface and will
// get its parent controller by asking for it specifically.
// IORegistryEntryGetParentEntry retains the returned object, so release it when we're done with it.
kernResult = IORegistryEntryGetParentEntry(intfService,
kIOServicePlane,
&controllerService);
if (KERN_SUCCESS != kernResult) {
printf("IORegistryEntryGetParentEntry returned 0x%08x\n", kernResult);
}
else {
// Retrieve the MAC address property from the I/O Registry in the form of a CFData
MACAddressAsCFData = IORegistryEntryCreateCFProperty(controllerService,
CFSTR(kIOMACAddress),
kCFAllocatorDefault,
0);
if (MACAddressAsCFData) {
CFShow(MACAddressAsCFData); // for display purposes only; output goes to stderr
// Get the raw bytes of the MAC address from the CFData
CFDataGetBytes(MACAddressAsCFData, CFRangeMake(0, kIOEthernetAddressSize), MACAddress);
CFRelease(MACAddressAsCFData);
}
// Done with the parent Ethernet controller object so we release it.
(void) IOObjectRelease(controllerService);
}
// Done with the Ethernet interface object so we release it.
(void) IOObjectRelease(intfService);
}
return kernResult;
}
- (void)createLocalMac{
kern_return_t kernResult = KERN_SUCCESS;
io_iterator_t intfIterator;
UInt8 MACAddress[kIOEthernetAddressSize];
kernResult = FindEthernetInterfaces(&intfIterator);
if (KERN_SUCCESS != kernResult) {
printf("FindEthernetInterfaces returned 0x%08x\n", kernResult);
}
else {
kernResult = GetMACAddress(intfIterator, MACAddress, sizeof(MACAddress));
if (KERN_SUCCESS != kernResult) {
printf("GetMACAddress returned 0x%08x\n", kernResult);
}
else {
localMac = [NSString stringWithFormat:#"%02x:%02x:%02x:%02x:%02x:%02x",
MACAddress[0], MACAddress[1], MACAddress[2], MACAddress[3], MACAddress[4], MACAddress[5]];
}
}
(void) IOObjectRelease(intfIterator); // Release the iterator.
}
//REMOTE MAC:::::::::::::::::::
- (void)createRemoteMac:(NSString *)ipAddr{
NSString *ret = nil;
in_addr_t addr = inet_addr([ipAddr UTF8String]);
size_t needed;
char *buf, *next;
struct rt_msghdr *rtm;
struct sockaddr_inarp *sin;
struct sockaddr_dl *sdl;
int mib[6];
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
mib[5] = RTF_LLINFO;
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &needed, NULL, 0) < 0)
err(1, "route-sysctl-estimate");
if ((buf = (char*)malloc(needed)) == NULL)
err(1, "malloc");
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &needed, NULL, 0) < 0)
err(1, "retrieval of routing table");
for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)next;
sin = (struct sockaddr_inarp *)(rtm + 1);
sdl = (struct sockaddr_dl *)(sin + 1);
if (addr != sin->sin_addr.s_addr || sdl->sdl_alen < 6)
continue;
u_char *cp = (u_char*)LLADDR(sdl);
ret = [NSString stringWithFormat:#"%02X:%02X:%02X:%02X:%02X:%02X",
cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]];
break;
}
free(buf);
remoteMac = ret;
}
- (void)dealloc {
[remoteMac release];
[localMac release];
[super dealloc];
}
#end
I use it to get the active interface's MAC address.
Your print statement is happening on this line using CFShow. Just comment that out :)
if (MACAddressAsCFData) {
//Comment out the CFShow here
CFShow(MACAddressAsCFData); // for display purposes only; output goes to stderr

Get a list of all available network interfaces (en0, en1, en2, etc) with Cocoa?

In my Cocoa application I want to show the user a list of available network interfaces, like Wireshark does:
What is the best way of getting such a list? Does Apple provide a framework for this, or must I use a C API from the standard library or another library?
Better than wrapping ifconfig you shall check the reference of SCNetworkConfiguration which is part of Core Foundation.
Check SCNetworkInterfaceXxx functions for details.
related answer:
Using Cocoa / Objective-C, get currently connected network's security type in Mac OS X
The following code will get all the interfaces from OS X through System Configuration, then use standard C functions to get the IP addresses (where available).
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <net/if.h>
#define IFT_ETHER 0x6
#include <SystemConfiguration/SCDynamicStore.h>
+(void)getInterfaces
{
SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)#"FindCurrentInterfaceIpMac", NULL, NULL);
CFPropertyListRef global = SCDynamicStoreCopyValue (storeRef,CFSTR("State:/Network/Interface"));
id primaryInterface = [(__bridge NSDictionary *)global valueForKey:#"Interfaces"];
for (NSString* item in primaryInterface)
{
if(get_iface_address([item UTF8String]))
{
NSString *ip = [NSString stringWithUTF8String:get_iface_address([item UTF8String])];
NSLog(#"interface: %# - %#",item,ip);
} else
NSLog(#"interface: %#",item);
}
}
static char * get_iface_address (char *interface)
{
int sock;
uint32_t ip;
struct ifreq ifr;
char *val;
if (!interface)
return NULL;
/* determine UDN according to MAC address */
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror ("socket");
return NULL;
}
strcpy (ifr.ifr_name, interface);
ifr.ifr_addr.sa_family = AF_INET;
if (ioctl (sock, SIOCGIFADDR, &ifr) < 0)
{
perror ("ioctl");
close (sock);
return NULL;
}
val = (char *) malloc (16 * sizeof (char));
ip = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr;
ip = ntohl (ip);
sprintf (val, "%d.%d.%d.%d",
(ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
close (sock);
return val;
}
#include <SystemConfiguration/SCDynamicStore.h>
SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)#"FindCurrentInterfaceIpMac", NULL, NULL);
CFPropertyListRef global = SCDynamicStoreCopyValue (storeRef,CFSTR("State:/Network/Interface"));
id primaryInterface = [(__bridge NSDictionary *)global valueForKey:#"Interfaces"];
for (NSString* item in primaryInterface)
{
NSLog(#"%#", item);
}
Your quickest and best bet is to write a wrapper for ifconfig command.