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

Ortham / libloadorder / 13090182207

01 Feb 2025 04:01PM UTC coverage: 92.365%. Remained the same
13090182207

push

github

Ortham
Set versions and changelogs for 18.2.0

9473 of 10256 relevant lines covered (92.37%)

1568044.73 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::panic::catch_unwind;
21
use std::ptr;
22

23
use libc::{c_char, c_uint, size_t};
24

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

×
221
        LIBLO_OK
×
222
    })
×
223
    .unwrap_or(LIBLO_ERROR_PANICKED)
×
224
}
×
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