]> git.saurik.com Git - apple/syslog.git/blob - aslmanager.tproj/cache_delete.c
1184fc215ed334f2ce3b2363123cefaaf1e8a58b
[apple/syslog.git] / aslmanager.tproj / cache_delete.c
1 /*
2 * Copyright (c) 2015 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 #include <CacheDelete/CacheDelete.h>
25 #include <CoreFoundation/CoreFoundation.h>
26 #include <asl.h>
27 #include "daemon.h"
28
29 /* CacheDelete ID (stored in cache delete plist). Must match suggested CacheDelete id naming conventions. */
30 #define CACHE_DELETE_ID "com.apple.activity_tracing.cache-delete"
31
32 #define CFSTR_FROM_DICT(dict, key) ({ \
33 void *strRef = NULL; \
34 if (dict != NULL) { \
35 strRef = (void *)CFDictionaryGetValue(dict, key); \
36 if ((strRef == NULL) || (CFStringGetTypeID() != CFGetTypeID(strRef))) strRef = NULL; \
37 } \
38 (CFStringRef)strRef; \
39 })
40
41 #define INT64_FROM_DICT(dict, key) ({ \
42 int64_t value = 0; \
43 if (dict != NULL) { \
44 void *numRef = (void *)CFDictionaryGetValue(dict, key); \
45 if (numRef && (CFNumberGetTypeID() == CFGetTypeID(numRef))) {\
46 if (!CFNumberGetValue(numRef, kCFNumberSInt64Type, &value)) value = 0; \
47 } \
48 } \
49 value; \
50 })
51
52 static int64_t
53 _purgeable(void)
54 {
55 size_t psize = 0;
56 int status = cache_delete_task(true, &psize);
57 if (status == 0) return (uint64_t)psize;
58 return 0;
59 }
60
61 static int64_t
62 _purge(int64_t purge_amount_bytes, CacheDeleteUrgency urgency)
63 {
64 size_t curr_size, new_size;
65 curr_size = 0;
66
67 int status = cache_delete_task(true, &curr_size);
68 if (status != 0) return 0;
69
70 new_size = curr_size - purge_amount_bytes;
71
72 status = cache_delete_task(false, &new_size);
73 if (status == 0) return new_size;
74
75 return 0;
76 }
77
78 static bool
79 _volume_contains_cached_data(CFStringRef volume)
80 {
81 return true;
82 }
83
84
85 static CFDictionaryRef
86 _handle_cache_delete_with_urgency(CFDictionaryRef info, CacheDeleteUrgency urgency, bool purge)
87 {
88 xpc_transaction_begin();
89
90 uint64_t amount_requested = INT64_FROM_DICT(info, CFSTR(CACHE_DELETE_AMOUNT_KEY));
91 CFStringRef volume_requested = CFSTR_FROM_DICT(info, CFSTR(CACHE_DELETE_VOLUME_KEY));
92
93 CFMutableDictionaryRef result = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
94 if (result == NULL)
95 {
96 goto bail;
97 }
98 else if (volume_requested == NULL)
99 {
100 goto bail;
101 }
102
103 /* TODO: CFStringGetCStringPtr can return NULL */
104 // debug_log(ASL_LEVEL_DEBUG, "CacheDelete request (purge=%d, urgency=%d, volume=%s, amount=%llu).", (int)urgency, CFStringGetCStringPtr(volume_requested, kCFStringEncodingUTF8), amount_requested);
105
106 int64_t amount_purged = 0;
107
108 if (_volume_contains_cached_data(volume_requested))
109 {
110 if (purge)
111 {
112 amount_purged = _purge(amount_requested, urgency);
113 // debug_log(ASL_LEVEL_WARNING, "Purged %lld bytes.", amount_purged);
114 }
115 else
116 {
117 amount_purged = _purgeable();
118 // debug_log(ASL_LEVEL_WARNING, "%lld bytes of purgeable space.", amount_purged);
119 }
120 }
121
122 CFNumberRef amount_purged_obj = CFNumberCreate(NULL, kCFNumberSInt64Type, &amount_purged);
123 if (amount_purged_obj != NULL)
124 {
125 CFDictionaryAddValue(result, CFSTR(CACHE_DELETE_AMOUNT_KEY), amount_purged_obj);
126 CFRelease(amount_purged_obj);
127 }
128
129 bail:
130
131 xpc_transaction_end();
132 return result;
133 }
134
135 bool
136 cache_delete_register(void)
137 {
138 return CacheDeleteRegisterInfoCallbacks(CFSTR(CACHE_DELETE_ID), ^CFDictionaryRef(CacheDeleteUrgency urgency, CFDictionaryRef info) {
139 /* Purgeable Space Request */
140 return _handle_cache_delete_with_urgency(info, urgency, false);
141 }, ^CFDictionaryRef(CacheDeleteUrgency urgency, CFDictionaryRef info) {
142 /* Purge Request */
143 return _handle_cache_delete_with_urgency(info, urgency, true);
144 }, NULL, NULL) == 0;
145 }