glib/functions.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3pub use crate::auto::functions::*;
4#[cfg(not(windows))]
5use std::boxed::Box as Box_;
6#[cfg(not(windows))]
7use std::mem;
8#[cfg(not(windows))]
9#[cfg(feature = "v2_58")]
10use std::os::unix::io::{AsFd, AsRawFd};
11#[cfg(not(windows))]
12use std::os::unix::io::{FromRawFd, OwnedFd};
13use std::ptr;
14
15// #[cfg(windows)]
16// #[cfg(feature = "v2_58")]
17// use std::os::windows::io::AsRawHandle;
18use crate::{ChecksumType, GStr, ffi, translate::*};
19#[cfg(not(windows))]
20use crate::{Error, Pid, SpawnFlags};
21
22#[cfg(feature = "v2_58")]
23#[cfg(not(windows))]
24#[cfg_attr(docsrs, doc(cfg(all(feature = "v2_58", not(windows)))))]
25#[allow(clippy::too_many_arguments)]
26#[doc(alias = "g_spawn_async_with_fds")]
27pub fn spawn_async_with_fds<P: AsRef<std::path::Path>>(
28 working_directory: P,
29 argv: &[&str],
30 envp: &[&str],
31 flags: SpawnFlags,
32 child_setup: Option<Box_<dyn FnOnce() + 'static>>,
33 stdin_fd: Option<impl AsFd>,
34 stdout_fd: Option<impl AsFd>,
35 stderr_fd: Option<impl AsFd>,
36) -> Result<Pid, Error> {
37 let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup);
38 unsafe extern "C" fn child_setup_func(user_data: ffi::gpointer) {
39 unsafe {
40 let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> =
41 Box_::from_raw(user_data as *mut _);
42 let callback = (*callback).expect("cannot get closure...");
43 callback()
44 }
45 }
46 let child_setup = if child_setup_data.is_some() {
47 Some(child_setup_func as _)
48 } else {
49 None
50 };
51 let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
52 let stdin_raw_fd = stdin_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
53 let stdout_raw_fd = stdout_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
54 let stderr_raw_fd = stderr_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
55 unsafe {
56 let mut child_pid = mem::MaybeUninit::uninit();
57 let mut error = ptr::null_mut();
58 let _ = ffi::g_spawn_async_with_fds(
59 working_directory.as_ref().to_glib_none().0,
60 argv.to_glib_none().0,
61 envp.to_glib_none().0,
62 flags.into_glib(),
63 child_setup,
64 Box_::into_raw(super_callback0) as *mut _,
65 child_pid.as_mut_ptr(),
66 stdin_raw_fd,
67 stdout_raw_fd,
68 stderr_raw_fd,
69 &mut error,
70 );
71 let child_pid = from_glib(child_pid.assume_init());
72 if error.is_null() {
73 Ok(child_pid)
74 } else {
75 Err(from_glib_full(error))
76 }
77 }
78}
79
80// #[cfg(feature = "v2_58")]
81// #[cfg(windows)]
82// pub fn spawn_async_with_fds<
83// P: AsRef<std::path::Path>,
84// T: AsRawHandle,
85// U: AsRawHandle,
86// V: AsRawHandle,
87// >(
88// working_directory: P,
89// argv: &[&str],
90// envp: &[&str],
91// flags: SpawnFlags,
92// child_setup: Option<Box_<dyn FnOnce() + 'static>>,
93// stdin_fd: T,
94// stdout_fd: U,
95// stderr_fd: V,
96// ) -> Result<Pid, Error> {
97// let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup);
98// unsafe extern "C" fn child_setup_func<P: AsRef<std::path::Path>>(
99// user_data: ffi::gpointer,
100// ) {
101// let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> =
102// Box_::from_raw(user_data as *mut _);
103// let callback = (*callback).expect("cannot get closure...");
104// callback()
105// }
106// let child_setup = if child_setup_data.is_some() {
107// Some(child_setup_func::<P> as _)
108// } else {
109// None
110// };
111// let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
112// unsafe {
113// let mut child_pid = mem::MaybeUninit::uninit();
114// let mut error = ptr::null_mut();
115// let _ = ffi::g_spawn_async_with_fds(
116// working_directory.as_ref().to_glib_none().0,
117// argv.to_glib_none().0,
118// envp.to_glib_none().0,
119// flags.into_glib(),
120// child_setup,
121// Box_::into_raw(super_callback0) as *mut _,
122// child_pid.as_mut_ptr(),
123// stdin_fd.as_raw_handle() as usize as _,
124// stdout_fd.as_raw_handle() as usize as _,
125// stderr_fd.as_raw_handle() as usize as _,
126// &mut error,
127// );
128// let child_pid = from_glib(child_pid.assume_init());
129// if error.is_null() {
130// Ok(child_pid)
131// } else {
132// Err(from_glib_full(error))
133// }
134// }
135// }
136
137#[cfg(not(windows))]
138#[cfg_attr(docsrs, doc(cfg(not(windows))))]
139#[doc(alias = "g_spawn_async_with_pipes")]
140pub fn spawn_async_with_pipes<
141 P: AsRef<std::path::Path>,
142 T: FromRawFd,
143 U: FromRawFd,
144 V: FromRawFd,
145>(
146 working_directory: P,
147 argv: &[&std::path::Path],
148 envp: &[&std::path::Path],
149 flags: SpawnFlags,
150 child_setup: Option<Box_<dyn FnOnce() + 'static>>,
151) -> Result<(Pid, T, U, V), Error> {
152 let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup);
153 unsafe extern "C" fn child_setup_func(user_data: ffi::gpointer) {
154 unsafe {
155 let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> =
156 Box_::from_raw(user_data as *mut _);
157 let callback = (*callback).expect("cannot get closure...");
158 callback()
159 }
160 }
161 let child_setup = if child_setup_data.is_some() {
162 Some(child_setup_func as _)
163 } else {
164 None
165 };
166 let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
167 unsafe {
168 let mut child_pid = mem::MaybeUninit::uninit();
169 let mut standard_input = mem::MaybeUninit::uninit();
170 let mut standard_output = mem::MaybeUninit::uninit();
171 let mut standard_error = mem::MaybeUninit::uninit();
172 let mut error = ptr::null_mut();
173 let _ = ffi::g_spawn_async_with_pipes(
174 working_directory.as_ref().to_glib_none().0,
175 argv.to_glib_none().0,
176 envp.to_glib_none().0,
177 flags.into_glib(),
178 child_setup,
179 Box_::into_raw(super_callback0) as *mut _,
180 child_pid.as_mut_ptr(),
181 standard_input.as_mut_ptr(),
182 standard_output.as_mut_ptr(),
183 standard_error.as_mut_ptr(),
184 &mut error,
185 );
186 if error.is_null() {
187 let child_pid = from_glib(child_pid.assume_init());
188 let standard_input = standard_input.assume_init();
189 let standard_output = standard_output.assume_init();
190 let standard_error = standard_error.assume_init();
191 #[cfg(not(windows))]
192 {
193 Ok((
194 child_pid,
195 FromRawFd::from_raw_fd(standard_input),
196 FromRawFd::from_raw_fd(standard_output),
197 FromRawFd::from_raw_fd(standard_error),
198 ))
199 }
200 // #[cfg(windows)]
201 // {
202 // use std::os::windows::io::{FromRawHandle, RawHandle};
203 // Ok((
204 // child_pid,
205 // File::from_raw_handle(standard_input as usize as RawHandle),
206 // File::from_raw_handle(standard_output as usize as RawHandle),
207 // File::from_raw_handle(standard_error as usize as RawHandle),
208 // ))
209 // }
210 } else {
211 Err(from_glib_full(error))
212 }
213 }
214}
215
216// rustdoc-stripper-ignore-next
217/// Obtain the character set for the current locale.
218///
219/// This returns whether the locale's encoding is UTF-8, and the current
220/// charset if available.
221#[doc(alias = "g_get_charset")]
222#[doc(alias = "get_charset")]
223pub fn charset() -> (bool, Option<&'static GStr>) {
224 unsafe {
225 let mut out_charset = ptr::null();
226 let is_utf8 = from_glib(ffi::g_get_charset(&mut out_charset));
227 let charset = from_glib_none(out_charset);
228 (is_utf8, charset)
229 }
230}
231
232/// Gets the current user's home directory.
233///
234/// As with most UNIX tools, this function will return the value of the
235/// `HOME` environment variable if it is set to an existing absolute path
236/// name, falling back to the `passwd` file in the case that it is unset.
237///
238/// If the path given in `HOME` is non-absolute, does not exist, or is
239/// not a directory, the result is undefined.
240///
241/// Before version 2.36 this function would ignore the `HOME` environment
242/// variable, taking the value from the `passwd` database instead. This was
243/// changed to increase the compatibility of GLib with other programs (and
244/// the XDG basedir specification) and to increase testability of programs
245/// based on GLib (by making it easier to run them from test frameworks).
246///
247/// If your program has a strong requirement for either the new or the
248/// old behaviour (and if you don't wish to increase your GLib
249/// dependency to ensure that the new behaviour is in effect) then you
250/// should either directly check the `HOME` environment variable yourself
251/// or unset it before calling any functions in GLib.
252///
253/// # Returns
254///
255/// the current user's home directory
256#[doc(alias = "g_get_home_dir")]
257#[doc(alias = "get_home_dir")]
258pub fn home_dir() -> &'static std::path::Path {
259 unsafe { c_to_path(ffi::g_get_home_dir()) }
260}
261
262/// Gets the directory to use for temporary files.
263///
264/// On UNIX, this is taken from the `TMPDIR` environment variable.
265/// If the variable is not set, `P_tmpdir` is
266/// used, as defined by the system C library. Failing that, a
267/// hard-coded default of "/tmp" is returned.
268///
269/// On Windows, the `TEMP` environment variable is used, with the
270/// root directory of the Windows installation (eg: "C:\") used
271/// as a default.
272///
273/// The encoding of the returned string is system-defined. On Windows,
274/// it is always UTF-8. The return value is never [`None`] or the empty
275/// string.
276///
277/// # Returns
278///
279/// the directory to use for temporary files.
280#[doc(alias = "g_get_tmp_dir")]
281#[doc(alias = "get_tmp_dir")]
282pub fn tmp_dir() -> &'static std::path::Path {
283 unsafe { c_to_path(ffi::g_get_tmp_dir()) }
284}
285
286/// Gets the user name of the current user. The encoding of the returned
287/// string is system-defined. On UNIX, it might be the preferred file name
288/// encoding, or something else, and there is no guarantee that it is even
289/// consistent on a machine. On Windows, it is always UTF-8.
290///
291/// # Returns
292///
293/// the user name of the current user.
294#[doc(alias = "g_get_user_name")]
295#[doc(alias = "get_user_name")]
296pub fn user_name() -> &'static std::ffi::OsStr {
297 unsafe { c_to_path(ffi::g_get_user_name()).as_os_str() }
298}
299
300/// Gets the real name of the user. This usually comes from the user's
301/// entry in the `passwd` file. The encoding of the returned string is
302/// system-defined. (On Windows, it is, however, always UTF-8.) If the
303/// real user name cannot be determined, the string "Unknown" is
304/// returned.
305///
306/// # Returns
307///
308/// the user's real name.
309#[doc(alias = "g_get_real_name")]
310#[doc(alias = "get_real_name")]
311pub fn real_name() -> &'static std::ffi::OsStr {
312 unsafe { c_to_path(ffi::g_get_real_name()).as_os_str() }
313}
314
315/// Return a name for the machine.
316///
317/// The returned name is not necessarily a fully-qualified domain name,
318/// or even present in DNS or some other name service at all. It need
319/// not even be unique on your local network or site, but usually it
320/// is. Callers should not rely on the return value having any specific
321/// properties like uniqueness for security purposes. Even if the name
322/// of the machine is changed while an application is running, the
323/// return value from this function does not change. The returned
324/// string is owned by GLib and should not be modified or freed. If no
325/// name can be determined, a default fixed string "localhost" is
326/// returned.
327///
328/// The encoding of the returned string is UTF-8.
329///
330/// # Returns
331///
332/// the host name of the machine.
333#[doc(alias = "g_get_host_name")]
334#[doc(alias = "get_host_name")]
335pub fn host_name() -> &'static GStr {
336 unsafe { GStr::from_ptr(ffi::g_get_host_name()) }
337}
338
339/// Returns a base directory in which to store non-essential, cached
340/// data specific to particular user.
341///
342/// On UNIX platforms this is determined using the mechanisms described
343/// in the
344/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
345/// In this case the directory retrieved will be `XDG_CACHE_HOME`.
346///
347/// On Windows it follows XDG Base Directory Specification if `XDG_CACHE_HOME` is defined.
348/// If `XDG_CACHE_HOME` is undefined, the directory that serves as a common
349/// repository for temporary Internet files is used instead. A typical path is
350/// `C:\Documents and Settings\username\Local Settings\Temporary Internet Files`.
351/// See the [documentation for `FOLDERID_InternetCache`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
352///
353/// The return value is cached and modifying it at runtime is not supported, as
354/// it’s not thread-safe to modify environment variables at runtime.
355///
356/// # Returns
357///
358/// a string owned by GLib that
359/// must not be modified or freed.
360#[doc(alias = "g_get_user_cache_dir")]
361#[doc(alias = "get_user_cache_dir")]
362pub fn user_cache_dir() -> &'static std::path::Path {
363 unsafe { c_to_path(ffi::g_get_user_cache_dir()) }
364}
365
366/// Returns a base directory in which to store user-specific application
367/// configuration information such as user preferences and settings.
368///
369/// On UNIX platforms this is determined using the mechanisms described
370/// in the
371/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
372/// In this case the directory retrieved will be `XDG_CONFIG_HOME`.
373///
374/// On Windows it follows XDG Base Directory Specification if `XDG_CONFIG_HOME` is defined.
375/// If `XDG_CONFIG_HOME` is undefined, the folder to use for local (as opposed
376/// to roaming) application data is used instead. See the
377/// [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
378/// Note that in this case on Windows it will be the same
379/// as what g_get_user_data_dir() returns.
380///
381/// The return value is cached and modifying it at runtime is not supported, as
382/// it’s not thread-safe to modify environment variables at runtime.
383///
384/// # Returns
385///
386/// a string owned by GLib that
387/// must not be modified or freed.
388#[doc(alias = "g_get_user_config_dir")]
389#[doc(alias = "get_user_config_dir")]
390pub fn user_config_dir() -> &'static std::path::Path {
391 unsafe { c_to_path(ffi::g_get_user_config_dir()) }
392}
393
394/// Returns a base directory in which to access application data such
395/// as icons that is customized for a particular user.
396///
397/// On UNIX platforms this is determined using the mechanisms described
398/// in the
399/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
400/// In this case the directory retrieved will be `XDG_DATA_HOME`.
401///
402/// On Windows it follows XDG Base Directory Specification if `XDG_DATA_HOME`
403/// is defined. If `XDG_DATA_HOME` is undefined, the folder to use for local (as
404/// opposed to roaming) application data is used instead. See the
405/// [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
406/// Note that in this case on Windows it will be the same
407/// as what g_get_user_config_dir() returns.
408///
409/// The return value is cached and modifying it at runtime is not supported, as
410/// it’s not thread-safe to modify environment variables at runtime.
411///
412/// # Returns
413///
414/// a string owned by GLib that must
415/// not be modified or freed.
416#[doc(alias = "g_get_user_data_dir")]
417#[doc(alias = "get_user_data_dir")]
418pub fn user_data_dir() -> &'static std::path::Path {
419 unsafe { c_to_path(ffi::g_get_user_data_dir()) }
420}
421
422/// Returns a directory that is unique to the current user on the local
423/// system.
424///
425/// This is determined using the mechanisms described
426/// in the
427/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
428/// This is the directory
429/// specified in the `XDG_RUNTIME_DIR` environment variable.
430/// In the case that this variable is not set, we return the value of
431/// g_get_user_cache_dir(), after verifying that it exists.
432///
433/// The return value is cached and modifying it at runtime is not supported, as
434/// it’s not thread-safe to modify environment variables at runtime.
435///
436/// # Returns
437///
438/// a string owned by GLib that must not be
439/// modified or freed.
440#[doc(alias = "g_get_user_runtime_dir")]
441#[doc(alias = "get_user_runtime_dir")]
442pub fn user_runtime_dir() -> &'static std::path::Path {
443 unsafe { c_to_path(ffi::g_get_user_runtime_dir()) }
444}
445
446/// Returns a base directory in which to store state files specific to
447/// particular user.
448///
449/// On UNIX platforms this is determined using the mechanisms described
450/// in the
451/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
452/// In this case the directory retrieved will be `XDG_STATE_HOME`.
453///
454/// On Windows it follows XDG Base Directory Specification if `XDG_STATE_HOME` is defined.
455/// If `XDG_STATE_HOME` is undefined, the folder to use for local (as opposed
456/// to roaming) application data is used instead. See the
457/// [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
458/// Note that in this case on Windows it will be the same
459/// as what g_get_user_data_dir() returns.
460///
461/// The return value is cached and modifying it at runtime is not supported, as
462/// it’s not thread-safe to modify environment variables at runtime.
463///
464/// # Returns
465///
466/// a string owned by GLib that
467/// must not be modified or freed.
468#[cfg(feature = "v2_72")]
469#[cfg_attr(docsrs, doc(cfg(feature = "v2_72")))]
470#[doc(alias = "g_get_user_state_dir")]
471#[doc(alias = "get_user_state_dir")]
472pub fn user_state_dir() -> &'static std::path::Path {
473 unsafe { c_to_path(ffi::g_get_user_state_dir()) }
474}
475
476/// Returns an ordered list of base directories in which to access
477/// system-wide application data.
478///
479/// On UNIX platforms this is determined using the mechanisms described
480/// in the
481/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec)
482/// In this case the list of directories retrieved will be `XDG_DATA_DIRS`.
483///
484/// On Windows it follows XDG Base Directory Specification if `XDG_DATA_DIRS` is defined.
485/// If `XDG_DATA_DIRS` is undefined,
486/// the first elements in the list are the Application Data
487/// and Documents folders for All Users. (These can be determined only
488/// on Windows 2000 or later and are not present in the list on other
489/// Windows versions.) See documentation for FOLDERID_ProgramData and
490/// FOLDERID_PublicDocuments.
491///
492/// Then follows the "share" subfolder in the installation folder for
493/// the package containing the DLL that calls this function, if it can
494/// be determined.
495///
496/// Finally the list contains the "share" subfolder in the installation
497/// folder for GLib, and in the installation folder for the package the
498/// application's .exe file belongs to.
499///
500/// The installation folders above are determined by looking up the
501/// folder where the module (DLL or EXE) in question is located. If the
502/// folder's name is "bin", its parent is used, otherwise the folder
503/// itself.
504///
505/// Note that on Windows the returned list can vary depending on where
506/// this function is called.
507///
508/// The return value is cached and modifying it at runtime is not supported, as
509/// it’s not thread-safe to modify environment variables at runtime.
510///
511/// # Returns
512///
513///
514/// a [`None`]-terminated array of strings owned by GLib that must not be
515/// modified or freed.
516#[doc(alias = "g_get_system_data_dirs")]
517#[doc(alias = "get_system_data_dirs")]
518pub fn system_data_dirs() -> &'static [&'static std::path::Path] {
519 static DIRS: std::sync::LazyLock<Vec<&'static std::path::Path>> =
520 std::sync::LazyLock::new(|| unsafe { strv_to_static_paths(ffi::g_get_system_data_dirs()) });
521
522 std::sync::LazyLock::force(&DIRS).as_slice()
523}
524
525/// Returns an ordered list of base directories in which to access
526/// system-wide configuration information.
527///
528/// On UNIX platforms this is determined using the mechanisms described
529/// in the
530/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
531/// In this case the list of directories retrieved will be `XDG_CONFIG_DIRS`.
532///
533/// On Windows it follows XDG Base Directory Specification if `XDG_CONFIG_DIRS` is defined.
534/// If `XDG_CONFIG_DIRS` is undefined, the directory that contains application
535/// data for all users is used instead. A typical path is
536/// `C:\Documents and Settings\All Users\Application Data`.
537/// This folder is used for application data
538/// that is not user specific. For example, an application can store
539/// a spell-check dictionary, a database of clip art, or a log file in the
540/// FOLDERID_ProgramData folder. This information will not roam and is available
541/// to anyone using the computer.
542///
543/// The return value is cached and modifying it at runtime is not supported, as
544/// it’s not thread-safe to modify environment variables at runtime.
545///
546/// # Returns
547///
548///
549/// a [`None`]-terminated array of strings owned by GLib that must not be
550/// modified or freed.
551#[doc(alias = "g_get_system_config_dirs")]
552#[doc(alias = "get_system_config_dirs")]
553pub fn system_config_dirs() -> &'static [&'static std::path::Path] {
554 static DIRS: std::sync::LazyLock<Vec<&'static std::path::Path>> =
555 std::sync::LazyLock::new(|| unsafe {
556 strv_to_static_paths(ffi::g_get_system_config_dirs())
557 });
558
559 std::sync::LazyLock::force(&DIRS).as_slice()
560}
561
562/// Computes a list of applicable locale names, which can be used to
563/// e.g. construct locale-dependent filenames or search paths. The returned
564/// list is sorted from most desirable to least desirable and always contains
565/// the default locale "C".
566///
567/// For example, if LANGUAGE=de:en_US, then the returned list is
568/// "de", "en_US", "en", "C".
569///
570/// This function consults the environment variables `LANGUAGE`, `LC_ALL`,
571/// `LC_MESSAGES` and `LANG` to find the list of locales specified by the
572/// user.
573///
574/// # Returns
575///
576/// a [`None`]-terminated array of strings owned by GLib
577/// that must not be modified or freed.
578#[doc(alias = "g_get_language_names")]
579#[doc(alias = "get_language_names")]
580pub fn language_names() -> &'static [crate::GStringPtr] {
581 unsafe { crate::StrV::from_glib_borrow(ffi::g_get_language_names()) }
582}
583
584unsafe fn strv_to_static_paths(
585 mut ptr: *const *const libc::c_char,
586) -> Vec<&'static std::path::Path> {
587 let mut paths = Vec::new();
588
589 unsafe {
590 while !(*ptr).is_null() {
591 paths.push(c_to_path(*ptr));
592 ptr = ptr.add(1);
593 }
594 }
595
596 paths
597}
598
599#[doc(alias = "g_compute_checksum_for_string")]
600pub fn compute_checksum_for_string(
601 checksum_type: ChecksumType,
602 str: impl IntoGStr,
603) -> Option<crate::GString> {
604 str.run_with_gstr(|str| unsafe {
605 from_glib_full(ffi::g_compute_checksum_for_string(
606 checksum_type.into_glib(),
607 str.as_ptr(),
608 str.len() as _,
609 ))
610 })
611}
612
613/// Opens a file for writing in the preferred directory for temporary
614/// files (as returned by g_get_tmp_dir()).
615///
616/// @tmpl should be a string in the GLib file name encoding containing
617/// a sequence of six 'X' characters, as the parameter to g_mkstemp().
618/// However, unlike these functions, the template should only be a
619/// basename, no directory components are allowed. If template is
620/// [`None`], a default template is used.
621///
622/// Note that in contrast to g_mkstemp() (and mkstemp()) @tmpl is not
623/// modified, and might thus be a read-only literal string.
624///
625/// Upon success, and if @name_used is non-[`None`], the actual name used
626/// is returned in @name_used. This string should be freed with g_free()
627/// when not needed any longer. The returned name is in the GLib file
628/// name encoding.
629/// ## `tmpl`
630/// Template for file name, as in
631/// g_mkstemp(), basename only, or [`None`] for a default template
632///
633/// # Returns
634///
635/// A file handle (as from open()) to the file opened for
636/// reading and writing. The file is opened in binary mode on platforms
637/// where there is a difference. The file handle should be closed with
638/// close(). In case of errors, -1 is returned and @error will be set.
639///
640/// ## `name_used`
641/// location to store actual name used,
642/// or [`None`]
643#[cfg(unix)]
644#[doc(alias = "g_file_open_tmp")]
645pub fn file_open_tmp(
646 tmpl: Option<impl AsRef<std::path::Path>>,
647) -> Result<(OwnedFd, std::path::PathBuf), crate::Error> {
648 unsafe {
649 let mut name_used = ptr::null_mut();
650 let mut error = ptr::null_mut();
651 let ret = ffi::g_file_open_tmp(
652 tmpl.as_ref().map(|p| p.as_ref()).to_glib_none().0,
653 &mut name_used,
654 &mut error,
655 );
656 if error.is_null() {
657 Ok((OwnedFd::from_raw_fd(ret), from_glib_full(name_used)))
658 } else {
659 Err(from_glib_full(error))
660 }
661 }
662}
663
664// rustdoc-stripper-ignore-next
665/// Spawn a new infallible `Future` on the thread-default main context.
666///
667/// This can be called from any thread and will execute the future from the thread
668/// where main context is running, e.g. via a `MainLoop`.
669#[cfg(feature = "futures")]
670pub fn spawn_future<R: Send + 'static, F: std::future::Future<Output = R> + Send + 'static>(
671 f: F,
672) -> crate::JoinHandle<R> {
673 let ctx = crate::MainContext::ref_thread_default();
674 ctx.spawn(f)
675}
676
677// rustdoc-stripper-ignore-next
678/// Spawn a new infallible `Future` on the thread-default main context.
679///
680/// The given `Future` does not have to be `Send`.
681///
682/// This can be called only from the thread where the main context is running, e.g.
683/// from any other `Future` that is executed on this main context, or after calling
684/// `with_thread_default` or `acquire` on the main context.
685#[cfg(feature = "futures")]
686pub fn spawn_future_local<R: 'static, F: std::future::Future<Output = R> + 'static>(
687 f: F,
688) -> crate::JoinHandle<R> {
689 let ctx = crate::MainContext::ref_thread_default();
690 ctx.spawn_local(f)
691}