Skip to main content

endpoint_sec/event/
event_btm_launch_item_add.rs

1//! [`EventBtmLaunchItemAdd`]
2
3use std::ffi::OsStr;
4
5use endpoint_sec_sys::{es_btm_item_type_t, es_btm_launch_item_t, es_event_btm_launch_item_add_t, uid_t};
6
7use crate::{AuditToken, Process};
8
9/// A launch item being made known to background task management.
10#[doc(alias = "es_event_btm_launch_item_add_t")]
11pub struct EventBtmLaunchItemAdd<'a> {
12    /// Raw event
13    pub(crate) raw: &'a es_event_btm_launch_item_add_t,
14    /// Message version
15    pub(crate) version: u32,
16}
17
18impl<'a> EventBtmLaunchItemAdd<'a> {
19    /// Optional. Process that instigated the BTM operation (XPC caller that asked for the item to
20    /// be added).
21    #[inline(always)]
22    pub fn instigator(&self) -> Option<Process<'a>> {
23        // Safety: 'a tied to self, object obtained through ES
24        let process = unsafe { self.raw.instigator()? };
25        Some(Process::new(process, self.version))
26    }
27
28    /// Audit token of the process that instigated this event.
29    pub fn instigator_token(&self) -> Option<AuditToken> {
30        #[cfg(feature = "macos_15_0_0")]
31        if self.version >= 8 {
32            // Safety: 'a tied to self, object obtained through ES
33            let token = unsafe { self.raw.instigator_token() };
34            return token.map(|v| AuditToken(*v));
35        }
36
37        // On older version, grab it from the instigator object.
38        self.instigator().map(|v| v.audit_token())
39    }
40
41    /// Optional. App process that registered the item.
42    #[inline(always)]
43    pub fn app(&self) -> Option<Process<'a>> {
44        // Safety: 'a tied to self, object obtained through ES
45        let process = unsafe { self.raw.app()? };
46        Some(Process::new(process, self.version))
47    }
48
49    /// Audit token of the process that instigated this event.
50    pub fn app_token(&self) -> Option<AuditToken> {
51        #[cfg(feature = "macos_15_0_0")]
52        if self.version >= 8 {
53            // Safety: 'a tied to self, object obtained through ES
54            let token = unsafe { self.raw.app_token() };
55            return token.map(|v| AuditToken(*v));
56        }
57
58        // On older version, grab it from the instigator object.
59        self.app().map(|v| v.audit_token())
60    }
61
62    /// BTM launch item.
63    #[inline(always)]
64    pub fn item(&self) -> BtmLaunchItem<'a> {
65        // Safety: 'a tied to self, object obtained through ES
66        BtmLaunchItem::new(unsafe { self.raw.item() })
67    }
68
69    /// Optional. If available and applicable, the POSIX executable path from the launchd plist. If
70    /// the path is relative, it is relative to `item.app_url`.
71    #[inline(always)]
72    pub fn executable_path(&self) -> &'a OsStr {
73        // Safety: 'a tied to self, object obtained through ES
74        unsafe { self.raw.executable_path.as_os_str() }
75    }
76}
77
78// Safety: safe to send across threads: does not contain any interior mutability nor depend on current thread state
79unsafe impl Send for EventBtmLaunchItemAdd<'_> {}
80// Safety: safe to share across threads: does not contain any interior mutability nor depend on current thread state
81unsafe impl Sync for EventBtmLaunchItemAdd<'_> {}
82
83impl_debug_eq_hash_with_functions!(
84    EventBtmLaunchItemAdd<'a>;
85    instigator, instigator_token, app, app_token, item, executable_path,
86);
87
88/// A BTM launch item
89#[doc(alias = "es_btm_launch_item_t")]
90pub struct BtmLaunchItem<'a> {
91    /// Raw data
92    pub(crate) raw: &'a es_btm_launch_item_t,
93}
94
95impl<'a> BtmLaunchItem<'a> {
96    /// New launch item
97    #[inline(always)]
98    pub(crate) fn new(raw: &'a es_btm_launch_item_t) -> Self {
99        Self { raw }
100    }
101
102    /// Type of launch item.
103    #[inline(always)]
104    pub fn item_type(&self) -> es_btm_item_type_t {
105        self.raw.item_type
106    }
107
108    /// True only if item is a legacy plist.
109    #[inline(always)]
110    pub fn legacy(&self) -> bool {
111        self.raw.legacy
112    }
113
114    /// True only if item is managed by MDM.
115    #[inline(always)]
116    pub fn managed(&self) -> bool {
117        self.raw.managed
118    }
119
120    /// User ID for the item (may be user `nobody` (`-2`)).
121    #[inline(always)]
122    pub fn uid(&self) -> uid_t {
123        self.raw.uid
124    }
125
126    /// URL for item.
127    ///
128    /// If a file URL describing a relative path, it is relative to `app_url`.
129    #[inline(always)]
130    pub fn item_url(&self) -> &'a OsStr {
131        // Safety: 'a tied to self, object obtained through ES
132        unsafe { self.raw.item_url.as_os_str() }
133    }
134
135    /// Optional. URL for app the item is attributed to.
136    #[inline(always)]
137    pub fn app_url(&self) -> &'a OsStr {
138        // Safety: 'a tied to self, object obtained through ES
139        unsafe { self.raw.app_url.as_os_str() }
140    }
141}
142
143// Safety: safe to send across threads: does not contain any interior mutability nor depend on current thread state
144unsafe impl Send for BtmLaunchItem<'_> {}
145
146impl_debug_eq_hash_with_functions!(
147    BtmLaunchItem<'a>;
148    item_type, legacy, managed, uid, item_url, app_url,
149);