]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCPUnlock.c
configd-1109.40.9.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCPUnlock.c
1 /*
2 * Copyright (c) 2000, 2001, 2004-2010, 2013, 2015, 2016, 2018 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
29 *
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
31 * - initial revision
32 */
33
34 #include "SCPreferencesInternal.h"
35 #include "SCHelper_client.h"
36
37 #include <unistd.h>
38 #include <pthread.h>
39
40
41 static Boolean
42 __SCPreferencesUnlock_helper(SCPreferencesRef prefs)
43 {
44 Boolean ok;
45 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
46 uint32_t status = kSCStatusOK;
47
48 if (prefsPrivate->helper_port == MACH_PORT_NULL) {
49 // if no helper
50 goto fail;
51 }
52
53 // have the helper "unlock" the prefs
54 // status = kSCStatusOK;
55 ok = _SCHelperExec(prefsPrivate->helper_port,
56 SCHELPER_MSG_PREFS_UNLOCK,
57 NULL,
58 &status,
59 NULL);
60 if (!ok) {
61 goto fail;
62 }
63
64 if (status != kSCStatusOK) {
65 goto error;
66 }
67
68 __SCPreferencesUpdateLockedState(prefs, FALSE);
69 return TRUE;
70
71 fail :
72
73 // close helper
74 if (prefsPrivate->helper_port != MACH_PORT_NULL) {
75 _SCHelperClose(&prefsPrivate->helper_port);
76 }
77
78 status = kSCStatusAccessError;
79
80 error :
81
82 // return error
83 _SCErrorSet(status);
84 return FALSE;
85 }
86
87
88 static void
89 reportDelay(SCPreferencesRef prefs, struct timeval *delay)
90 {
91 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
92
93 SC_log(LOG_ERR,
94 "SCPreferences(%@:%@) lock held for %d.%3.3d seconds",
95 prefsPrivate->name,
96 prefsPrivate->prefsID,
97 (int)delay->tv_sec,
98 delay->tv_usec / 1000);
99 return;
100 }
101
102
103 Boolean
104 SCPreferencesUnlock(SCPreferencesRef prefs)
105 {
106 struct timeval lockElapsed;
107 struct timeval lockEnd;
108 SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
109
110 if (prefs == NULL) {
111 /* sorry, you must provide a session */
112 _SCErrorSet(kSCStatusNoPrefsSession);
113 return FALSE;
114 }
115
116 if (!prefsPrivate->locked) {
117 /* sorry, you don't have the lock */
118 _SCErrorSet(kSCStatusNeedLock);
119 return FALSE;
120 }
121
122 if (prefsPrivate->authorizationData != NULL) {
123 return __SCPreferencesUnlock_helper(prefs);
124 }
125
126 pthread_mutex_lock(&prefsPrivate->lock);
127
128 if (prefsPrivate->sessionNoO_EXLOCK != NULL) {
129 // Note: closing the session removes the temporary "lock" key
130 CFRelease(prefsPrivate->sessionNoO_EXLOCK);
131 prefsPrivate->sessionNoO_EXLOCK = NULL;
132 }
133
134 if (prefsPrivate->lockFD != -1) {
135 if (prefsPrivate->lockPath != NULL) {
136 unlink(prefsPrivate->lockPath);
137 }
138 close(prefsPrivate->lockFD);
139 prefsPrivate->lockFD = -1;
140 }
141
142 (void)gettimeofday(&lockEnd, NULL);
143 timersub(&lockEnd, &prefsPrivate->lockTime, &lockElapsed);
144 if (lockElapsed.tv_sec > 0) {
145 // if we held the lock for more than 1 second
146 reportDelay(prefs, &lockElapsed);
147 }
148
149 SC_log(LOG_DEBUG, "SCPreferences() unlock: %s",
150 prefsPrivate->newPath ? prefsPrivate->newPath : prefsPrivate->path);
151
152 __SCPreferencesUpdateLockedState(prefs, FALSE);
153
154 pthread_mutex_unlock(&prefsPrivate->lock);
155 return TRUE;
156 }