• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Ortham / libloadorder / 14550006484

19 Apr 2025 02:17PM UTC coverage: 93.009% (+1.4%) from 91.59%
14550006484

push

github

Ortham
Update transitive dependencies

10576 of 11371 relevant lines covered (93.01%)

1415008.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/ffi/src/active_plugins.rs
1
/*
2
 * This file is part of libloadorder
3
 *
4
 * Copyright (C) 2017 Oliver Hamlet
5
 *
6
 * libloadorder is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * libloadorder is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with libloadorder. If not, see <http://www.gnu.org/licenses/>.
18
 */
19

20
use std::ffi::{c_char, c_uint};
21
use std::panic::catch_unwind;
22
use std::ptr;
23

24
use libc::size_t;
25

26
use super::lo_game_handle;
27
use crate::constants::*;
28
use crate::helpers::{error, handle_error, to_c_string_array, to_str, to_str_vec};
29

30
/// Gets the list of currently active plugins.
31
///
32
/// If no plugins are active, the value pointed to by `plugins` will be null and `num_plugins` will
33
/// point to zero.
34
///
35
/// Returns `LIBLO_OK` if successful, otherwise a `LIBLO_ERROR_*` code is returned.
36
///
37
/// # Safety
38
///
39
/// - `handle` must be a value that was previously set by `lo_create_handle()` and that has not been
40
///   destroyed using `lo_destroy_handle()`.
41
/// - `plugins` must be a dereferenceable pointer.
42
/// - `num_plugins` must be a dereferenceable pointer.
43
#[no_mangle]
44
pub unsafe extern "C" fn lo_get_active_plugins(
×
45
    handle: lo_game_handle,
×
46
    plugins: *mut *mut *mut c_char,
×
47
    num_plugins: *mut size_t,
×
48
) -> c_uint {
×
49
    catch_unwind(|| {
×
50
        if handle.is_null() || plugins.is_null() || num_plugins.is_null() {
×
51
            return error(LIBLO_ERROR_INVALID_ARGS, "Null pointer passed");
×
52
        }
×
53

54
        let handle = match (*handle).read() {
×
55
            Err(e) => return error(LIBLO_ERROR_POISONED_THREAD_LOCK, &e.to_string()),
×
56
            Ok(h) => h,
×
57
        };
×
58

×
59
        *plugins = ptr::null_mut();
×
60
        *num_plugins = 0;
×
61

×
62
        let active_plugins = handle.active_plugin_names();
×
63

×
64
        if active_plugins.is_empty() {
×
65
            return LIBLO_OK;
×
66
        }
×
67

×
68
        match to_c_string_array(&active_plugins) {
×
69
            Ok((pointer, size)) => {
×
70
                *plugins = pointer;
×
71
                *num_plugins = size;
×
72
            }
×
73
            Err(x) => return error(x, "A filename contained a null byte"),
×
74
        }
75

76
        LIBLO_OK
×
77
    })
×
78
    .unwrap_or(LIBLO_ERROR_PANICKED)
×
79
}
×
80

81
/// Sets the list of currently active plugins.
82
///
83
/// Replaces the current active plugins list with the plugins in the given array. The replacement
84
/// list must be valid. If, for Skyrim or Fallout 4, a plugin to be activated does not have a
85
/// defined load order position, this function will append it to the load order. If multiple such
86
/// plugins exist, they are appended in the order they are given.
87
///
88
/// Returns `LIBLO_OK` if successful, otherwise a `LIBLO_ERROR_*` code is returned.
89
///
90
/// # Safety
91
///
92
/// - `handle` must be a value that was previously set by `lo_create_handle()` and that has not been
93
///   destroyed using `lo_destroy_handle()`.
94
/// - `plugins` must be a non-null aligned pointer to a sequence of `num_plugins` initialised C
95
///   strings within a single allocated object.
96
/// - `num_plugins * std::mem::size_of::<*const c_char>()` must be no larger than `isize::MAX`.
97
#[no_mangle]
98
pub unsafe extern "C" fn lo_set_active_plugins(
×
99
    handle: lo_game_handle,
×
100
    plugins: *const *const c_char,
×
101
    num_plugins: size_t,
×
102
) -> c_uint {
×
103
    catch_unwind(|| {
×
104
        if handle.is_null() || plugins.is_null() {
×
105
            return error(LIBLO_ERROR_INVALID_ARGS, "Null pointer passed");
×
106
        }
×
107

108
        let mut handle = match (*handle).write() {
×
109
            Err(e) => return error(LIBLO_ERROR_POISONED_THREAD_LOCK, &e.to_string()),
×
110
            Ok(h) => h,
×
111
        };
112

113
        let plugins: Vec<&str> = match to_str_vec(plugins, num_plugins) {
×
114
            Ok(x) => x,
×
115
            Err(x) => return error(x, "A filename contained a null byte"),
×
116
        };
117

118
        if let Err(x) = handle.set_active_plugins(&plugins) {
×
119
            return handle_error(x);
×
120
        }
×
121

122
        if let Err(x) = handle.save() {
×
123
            return handle_error(x);
×
124
        }
×
125

×
126
        LIBLO_OK
×
127
    })
×
128
    .unwrap_or(LIBLO_ERROR_PANICKED)
×
129
}
×
130

131
/// Activates or deactivates a given plugin.
132
///
133
/// If `active` is true, the plugin will be activated. If `active` is false, the plugin will be
134
/// deactivated.
135
///
136
/// When activating a plugin that is ghosted, the ".ghost" extension is removed. If a plugin is
137
/// already in its target state, ie. a plugin to be activated is already activate, or a plugin to
138
/// be deactivated is already inactive, no changes are made.
139
///
140
/// Returns `LIBLO_OK` if successful, otherwise a `LIBLO_ERROR_*` code is returned.
141
///
142
/// # Safety
143
///
144
/// - `handle` must be a value that was previously set by `lo_create_handle()` and that has not been
145
///   destroyed using `lo_destroy_handle()`.
146
/// - `plugin` must be a null-terminated string contained within a single allocation.
147
#[no_mangle]
148
pub unsafe extern "C" fn lo_set_plugin_active(
×
149
    handle: lo_game_handle,
×
150
    plugin: *const c_char,
×
151
    active: bool,
×
152
) -> c_uint {
×
153
    catch_unwind(|| {
×
154
        if handle.is_null() || plugin.is_null() {
×
155
            return error(LIBLO_ERROR_INVALID_ARGS, "Null pointer passed");
×
156
        }
×
157

158
        let mut handle = match (*handle).write() {
×
159
            Err(e) => return error(LIBLO_ERROR_POISONED_THREAD_LOCK, &e.to_string()),
×
160
            Ok(h) => h,
×
161
        };
162

163
        let plugin = match to_str(plugin) {
×
164
            Ok(x) => x,
×
165
            Err(x) => return error(x, "The filename contained a null byte"),
×
166
        };
167

168
        let result = if active {
×
169
            handle.activate(plugin)
×
170
        } else {
171
            handle.deactivate(plugin)
×
172
        };
173

174
        if let Err(x) = result {
×
175
            return handle_error(x);
×
176
        }
×
177

178
        if let Err(x) = handle.save() {
×
179
            return handle_error(x);
×
180
        }
×
181

×
182
        LIBLO_OK
×
183
    })
×
184
    .unwrap_or(LIBLO_ERROR_PANICKED)
×
185
}
×
186

187
/// Checks if a given plugin is active.
188
///
189
/// Outputs `true` if the plugin is active, and false otherwise.
190
///
191
/// Returns `LIBLO_OK` if successful, otherwise a `LIBLO_ERROR_*` code is returned.
192
///
193
/// # Safety
194
///
195
/// - `handle` must be a value that was previously set by `lo_create_handle()` and that has not been
196
///   destroyed using `lo_destroy_handle()`.
197
/// - `plugin` must be a null-terminated string contained within a single allocation.
198
/// - `result` must be a dereferenceable pointer.
199
#[no_mangle]
200
pub unsafe extern "C" fn lo_get_plugin_active(
×
201
    handle: lo_game_handle,
×
202
    plugin: *const c_char,
×
203
    result: *mut bool,
×
204
) -> c_uint {
×
205
    catch_unwind(|| {
×
206
        if handle.is_null() || plugin.is_null() || result.is_null() {
×
207
            return error(LIBLO_ERROR_INVALID_ARGS, "Null pointer passed");
×
208
        }
×
209

210
        let handle = match (*handle).read() {
×
211
            Err(e) => return error(LIBLO_ERROR_POISONED_THREAD_LOCK, &e.to_string()),
×
212
            Ok(h) => h,
×
213
        };
214

215
        let plugin = match to_str(plugin) {
×
216
            Ok(x) => x,
×
217
            Err(x) => return error(x, "The filename contained a null byte"),
×
218
        };
219

220
        *result = handle.is_active(plugin);
×
221

×
222
        LIBLO_OK
×
223
    })
×
224
    .unwrap_or(LIBLO_ERROR_PANICKED)
×
225
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc