]> git.saurik.com Git - apple/syslog.git/blame - aslmanager.tproj/cache_delete.c
syslog-356.1.1.tar.gz
[apple/syslog.git] / aslmanager.tproj / cache_delete.c
CommitLineData
5222c21d
A
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
52static 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
61static 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
78static bool
79_volume_contains_cached_data(CFStringRef volume)
80{
81 return true;
82}
83
84
85static 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
129bail:
130
131 xpc_transaction_end();
132 return result;
133}
134
135bool
136cache_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}