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

jtmoon79 / super-speedy-syslog-searcher / 18082229368

29 Sep 2025 12:40AM UTC coverage: 69.783% (+0.2%) from 69.601%
18082229368

push

github

jtmoon79
(LIB) pin ctrlc=3.4.7

14415 of 20657 relevant lines covered (69.78%)

35839.2 hits per line

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

71.61
/src/data/fixedstruct.rs
1
// src/data/fixedstruct.rs
2

3
//! Implement [`FixedStruct`] to represent Unix record-keeping C structs.
4
//! This includes [`acct`], [`lastlog`], [`lastlogx`],
5
//! [`utmp`], and [`utmpx`] formats for various operating systems and
6
//! architectures.
7
//!
8
//! [`acct`]: https://www.man7.org/linux/man-pages/man5/acct.5.html
9
//! [`lastlog`]: https://man7.org/linux/man-pages/man8/lastlog.8.html
10
//! [`lastlogx`]: https://man.netbsd.org/lastlogx.5
11
//! [`utmp`]: https://www.man7.org/linux/man-pages/man5/utmp.5.html
12
//! [`utmpx`]: https://man.netbsd.org/utmpx.5
13

14
#![allow(clippy::tabs_in_doc_comments)]
15

16
use core::panic;
17
use std::collections::HashMap;
18
use std::ffi::CStr;
19
use std::fmt;
20
use std::io::{
21
    Error,
22
    ErrorKind,
23
};
24

25
use ::const_format::assertcp;
26
#[allow(unused_imports)]
27
use ::more_asserts::{
28
    assert_ge,
29
    assert_gt,
30
    assert_le,
31
    assert_lt,
32
    debug_assert_ge,
33
    debug_assert_gt,
34
    debug_assert_le,
35
    debug_assert_lt,
36
};
37
#[allow(unused_imports)]
38
use ::si_trace_print::{
39
    defn,
40
    defo,
41
    defx,
42
    defñ,
43
    den,
44
    deo,
45
    dex,
46
    deñ,
47
};
48
use numtoa::NumToA; // adds `numtoa` method to numbers
49

50
#[doc(hidden)]
51
use crate::common::{
52
    max16,
53
    min16,
54
    FileOffset,
55
    FileSz,
56
    FileTypeFixedStruct,
57
};
58
use crate::data::datetime::{
59
    DateTimeL,
60
    FixedOffset,
61
    LocalResult,
62
    TimeZone,
63
};
64
#[cfg(any(debug_assertions, test))]
65
use crate::debug::printers::byte_to_char_noraw;
66
use crate::readers::blockreader::{
67
    BlockOffset,
68
    BlockReader,
69
    BlockSz,
70
};
71
#[doc(hidden)]
72
use crate::{
73
    de_err,
74
    de_wrn,
75
    debug_panic,
76
};
77

78
/// size of the `[u8]` buffer used for `numtoa` conversions
79
/// good up to `i64::MAX` or `i64::MIN` plus a little "just in case" head room
80
pub const NUMTOA_BUF_SZ: usize = 22;
81

82
/// A scoring system for the quality of the data in a [`FixedStruct`]. A higher
83
/// score means the data is more likely to be the [`FixedStructType`] expected.
84
pub type Score = i32;
85

86
/// Helper to [`FixedStructType::tv_pair_from_buffer`].
87
macro_rules! buffer_to_timeval {
88
    ($timeval_type:ty, $timeval_sz:expr, $buffer:ident, $tv_sec:ident, $tv_usec:ident) => {{
89
        {
90
            // ut_tv
91
            let size: usize = $timeval_sz;
92
            defo!("size {:?}", size);
93
            debug_assert_eq!($buffer.len(), size);
94
            let time_val: $timeval_type = unsafe { *($buffer.as_ptr() as *const $timeval_type) };
95
            // XXX: copy to local variable to avoid alignment warning
96
            //      see #82523 <https://github.com/rust-lang/rust/issues/82523>
97
            let _tv_sec = time_val.tv_sec;
98
            let _tv_usec = time_val.tv_usec;
99
            defo!("time_val.tv_sec {:?} .tv_usec {:?}", _tv_sec, _tv_usec);
100
            // ut_tv.tv_sec
101
            $tv_sec = match time_val.tv_sec.try_into() {
102
                Ok(val) => val,
103
                Err(_) => {
104
                    debug_panic!("tv_sec overflow: {:?}", _tv_sec);
105
                    return None;
106
                }
107
            };
108
            defo!("tv_sec {:?}", $tv_sec);
109
            // ut_tv.tv_usec
110
            $tv_usec = match time_val.tv_usec.try_into() {
111
                Ok(val) => val,
112
                Err(_) => {
113
                    debug_panic!("tv_usec overflow: {:?}", _tv_usec);
114

115
                    0
116
                }
117
            };
118
            defo!("tv_usec {:?}", $tv_usec);
119
        }
120
    }};
121
}
122

123
macro_rules! buffer_to_time_t {
124
    ($ll_time_t:ty, $ll_time_sz:expr, $buffer:ident, $tv_sec:ident) => {{
125
        {
126
            let size: usize = $ll_time_sz;
127
            defo!("size {:?}", size);
128
            debug_assert_eq!($buffer.len(), size);
129
            let ll_time: $ll_time_t = unsafe { *($buffer.as_ptr() as *const $ll_time_t) };
130
            defo!("ll_time {:?}", ll_time);
131
            $tv_sec = match ll_time.try_into() {
132
                Ok(val) => val,
133
                Err(_) => {
134
                    debug_panic!("tv_sec overflow from ll_time {:?}", ll_time);
135
                    return None;
136
                }
137
            };
138
            defo!("tv_sec {:?}", $tv_sec);
139
        }
140
    }};
141
}
142

143
/// Helper to [`FixedStructType::tv_pair_from_buffer`].
144
/// Debug print the `DateTimeL` conversion of a `tv_pair`.
145
macro_rules! defo_tv_pair {
146
    ($tv_sec:ident, $tv_usec:ident) => {{
147
        {
148
            #[cfg(any(debug_assertions, test))]
149
            {
150
                let tz_offset: FixedOffset = FixedOffset::east_opt(0).unwrap();
151
                let tv_pair = tv_pair_type($tv_sec, $tv_usec);
152
                match convert_tvpair_to_datetime(tv_pair, &tz_offset) {
153
                    Ok(_dt) => {
154
                        defo!("dt: {:?}", _dt);
155
                    }
156
                    Err(err) => {
157
                        de_err!("{:?}", err);
158
                        panic!("convert_tvpair_to_datetime({:?}) returned an error; {}", tv_pair, err);
159
                    }
160
                }
161
            }
162
        }
163
    }};
164
}
165

166
/// FixedStruct Implementation Type (name `FixedStructType` is taken).
167
///
168
/// The specific implementation of the FixedStruct. Each implementation of,
169
/// for example, a `utmp` struct, differs in fields and sizes among Operating
170
/// Systems FreeBSD, Linux, OpenBSD, and NetBSD. and also differ per CPU
171
/// architecture, e.g. x86_64 vs. i386 vs. ARM7
172
#[allow(non_camel_case_types)]
173
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
174
pub enum FixedStructType {
175

176
    // FreeBSD x86_64 (amd64), x86_32 (i686)
177

178
    /// corresponds to [`freebsd_x8664::utmpx`]
179
    #[allow(non_camel_case_types)]
180
    Fs_Freebsd_x8664_Utmpx,
181

182
    // Linux
183

184
    // Linux ARM64 (aarch64)
185

186
    /// corresponds to [`linux_arm64aarch64::lastlog`]
187
    #[allow(non_camel_case_types)]
188
    Fs_Linux_Arm64Aarch64_Lastlog,
189

190
    /// corresponds to [`linux_arm64aarch64::utmpx`]
191
    #[allow(non_camel_case_types)]
192
    Fs_Linux_Arm64Aarch64_Utmpx,
193

194
    // Linux x86
195

196
    /// corresponds to [`linux_x86::acct`]
197
    #[allow(non_camel_case_types)]
198
    Fs_Linux_x86_Acct,
199

200
    /// corresponds to [`linux_x86::acct_v3`]
201
    #[allow(non_camel_case_types)]
202
    Fs_Linux_x86_Acct_v3,
203

204
    /// corresponds to [`linux_x86::lastlog`]
205
    #[allow(non_camel_case_types)]
206
    Fs_Linux_x86_Lastlog,
207

208
    /// corresponds to [`linux_x86::utmpx`]
209
    #[allow(non_camel_case_types)]
210
    Fs_Linux_x86_Utmpx,
211

212
    // NetBSD
213

214
    // NetBSD 9 x86_32 (i686)
215

216
    /// corresponds to [`netbsd_x8632::acct`]
217
    #[allow(non_camel_case_types)]
218
    Fs_Netbsd_x8632_Acct,
219

220
    /// corresponds to [`netbsd_x8632::lastlogx`]
221
    #[allow(non_camel_case_types)]
222
    Fs_Netbsd_x8632_Lastlogx,
223

224
    /// corresponds to [`netbsd_x8632::utmpx`]
225
    #[allow(non_camel_case_types)]
226
    Fs_Netbsd_x8632_Utmpx,
227

228
    // NetBSD 9 x86_64 (AMD64)
229

230
    /// corresponds to [`netbsd_x8664::lastlog`]
231
    #[allow(non_camel_case_types)]
232
    Fs_Netbsd_x8664_Lastlog,
233

234
    /// corresponds to [`netbsd_x8664::lastlogx`]
235
    #[allow(non_camel_case_types)]
236
    Fs_Netbsd_x8664_Lastlogx,
237

238
    /// corresponds to [`netbsd_x8664::utmp`]
239
    #[allow(non_camel_case_types)]
240
    Fs_Netbsd_x8664_Utmp,
241

242
    /// corresponds to [`netbsd_x8664::utmpx`]
243
    #[allow(non_camel_case_types)]
244
    Fs_Netbsd_x8664_Utmpx,
245

246
    // OpenBSD x86_32, x86_64
247

248
    /// corresponds to [`openbsd_x86::lastlog`]
249
    #[allow(non_camel_case_types)]
250
    Fs_Openbsd_x86_Lastlog,
251

252
    /// corresponds to [`openbsd_x86::utmp`]
253
    #[allow(non_camel_case_types)]
254
    Fs_Openbsd_x86_Utmp,
255
}
256

257
impl FixedStructType {
258
    /// return the associated `FixedStructType`'s `SZ` value (size in bytes).
259
    pub const fn size(&self) -> usize {
9,751✔
260
        match self {
9,751✔
261
            FixedStructType::Fs_Freebsd_x8664_Utmpx => freebsd_x8664::UTMPX_SZ,
4✔
262
            FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => linux_arm64aarch64::LASTLOG_SZ,
3✔
263
            FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => linux_arm64aarch64::UTMPX_SZ,
3✔
264
            FixedStructType::Fs_Linux_x86_Acct => linux_x86::ACCT_SZ,
1,852✔
265
            FixedStructType::Fs_Linux_x86_Acct_v3 => linux_x86::ACCT_V3_SZ,
1,852✔
266
            FixedStructType::Fs_Linux_x86_Lastlog => linux_x86::LASTLOG_SZ,
52✔
267
            FixedStructType::Fs_Linux_x86_Utmpx => linux_x86::UTMPX_SZ,
3,377✔
268
            FixedStructType::Fs_Netbsd_x8632_Acct => netbsd_x8632::ACCT_SZ,
3✔
269
            FixedStructType::Fs_Netbsd_x8632_Lastlogx => netbsd_x8632::LASTLOGX_SZ,
3✔
270
            FixedStructType::Fs_Netbsd_x8632_Utmpx => netbsd_x8632::UTMPX_SZ,
3✔
271
            FixedStructType::Fs_Netbsd_x8664_Lastlog => netbsd_x8664::LASTLOG_SZ,
2,584✔
272
            FixedStructType::Fs_Netbsd_x8664_Lastlogx => netbsd_x8664::LASTLOGX_SZ,
3✔
273
            FixedStructType::Fs_Netbsd_x8664_Utmp => netbsd_x8664::UTMP_SZ,
3✔
274
            FixedStructType::Fs_Netbsd_x8664_Utmpx => netbsd_x8664::UTMPX_SZ,
3✔
275
            FixedStructType::Fs_Openbsd_x86_Lastlog => openbsd_x86::LASTLOG_SZ,
3✔
276
            FixedStructType::Fs_Openbsd_x86_Utmp => openbsd_x86::UTMP_SZ,
3✔
277
        }
278
    }
9,751✔
279

280
    /// return the associated `FixedStructType`'s offset to it's ***t***ime
281
    /// ***v***alue field
282
    pub const fn offset_tv(&self) -> usize {
190✔
283
        match self {
190✔
284
            FixedStructType::Fs_Freebsd_x8664_Utmpx => freebsd_x8664::UTMPX_TIMEVALUE_OFFSET,
×
285
            FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => linux_arm64aarch64::LASTLOG_TIMEVALUE_OFFSET,
×
286
            FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => linux_arm64aarch64::UTMPX_TIMEVALUE_OFFSET,
×
287
            FixedStructType::Fs_Linux_x86_Acct => linux_x86::ACCT_TIMEVALUE_OFFSET,
×
288
            FixedStructType::Fs_Linux_x86_Acct_v3 => linux_x86::ACCT_V3_TIMEVALUE_OFFSET,
×
289
            FixedStructType::Fs_Linux_x86_Lastlog => linux_x86::LASTLOG_TIMEVALUE_OFFSET,
7✔
290
            FixedStructType::Fs_Linux_x86_Utmpx => linux_x86::UTMPX_TIMEVALUE_OFFSET,
183✔
291
            FixedStructType::Fs_Netbsd_x8632_Acct => netbsd_x8632::ACCT_TIMEVALUE_OFFSET,
×
292
            FixedStructType::Fs_Netbsd_x8632_Lastlogx => netbsd_x8632::LASTLOGX_TIMEVALUE_OFFSET,
×
293
            FixedStructType::Fs_Netbsd_x8632_Utmpx => netbsd_x8632::UTMPX_TIMEVALUE_OFFSET,
×
294
            FixedStructType::Fs_Netbsd_x8664_Lastlog => netbsd_x8664::LASTLOG_TIMEVALUE_OFFSET,
×
295
            FixedStructType::Fs_Netbsd_x8664_Lastlogx => netbsd_x8664::LASTLOGX_TIMEVALUE_OFFSET,
×
296
            FixedStructType::Fs_Netbsd_x8664_Utmp => netbsd_x8664::UTMP_TIMEVALUE_OFFSET,
×
297
            FixedStructType::Fs_Netbsd_x8664_Utmpx => netbsd_x8664::UTMPX_TIMEVALUE_OFFSET,
×
298
            FixedStructType::Fs_Openbsd_x86_Lastlog => openbsd_x86::LASTLOG_TIMEVALUE_OFFSET,
×
299
            FixedStructType::Fs_Openbsd_x86_Utmp => openbsd_x86::UTMP_TIMEVALUE_OFFSET,
×
300
        }
301
    }
190✔
302

303
    /// return the associated `FixedStructType`'s size of it's
304
    /// ***t***ime ***v***alue in bytes
305
    pub const fn size_tv(&self) -> usize {
1,367✔
306
        match self {
1,367✔
307
            FixedStructType::Fs_Freebsd_x8664_Utmpx => freebsd_x8664::UTMPX_TIMEVALUE_SZ,
×
308
            FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => linux_arm64aarch64::LASTLOG_TIMEVALUE_SZ,
×
309
            FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => linux_arm64aarch64::UTMPX_TIMEVALUE_SZ,
×
310
            FixedStructType::Fs_Linux_x86_Acct => linux_x86::ACCT_TIMEVALUE_SZ,
×
311
            FixedStructType::Fs_Linux_x86_Acct_v3 => linux_x86::ACCT_V3_TIMEVALUE_SZ,
×
312
            FixedStructType::Fs_Linux_x86_Lastlog => linux_x86::LASTLOG_TIMEVALUE_SZ,
14✔
313
            FixedStructType::Fs_Linux_x86_Utmpx => linux_x86::UTMPX_TIMEVALUE_SZ,
1,353✔
314
            FixedStructType::Fs_Netbsd_x8632_Acct => netbsd_x8632::ACCT_TIMEVALUE_SZ,
×
315
            FixedStructType::Fs_Netbsd_x8632_Lastlogx => netbsd_x8632::LASTLOGX_TIMEVALUE_SZ,
×
316
            FixedStructType::Fs_Netbsd_x8632_Utmpx => netbsd_x8632::UTMPX_TIMEVALUE_SZ,
×
317
            FixedStructType::Fs_Netbsd_x8664_Lastlog => netbsd_x8664::LASTLOG_TIMEVALUE_SZ,
×
318
            FixedStructType::Fs_Netbsd_x8664_Lastlogx => netbsd_x8664::LASTLOGX_TIMEVALUE_SZ,
×
319
            FixedStructType::Fs_Netbsd_x8664_Utmp => netbsd_x8664::UTMP_TIMEVALUE_SZ,
×
320
            FixedStructType::Fs_Netbsd_x8664_Utmpx => netbsd_x8664::UTMPX_TIMEVALUE_SZ,
×
321
            FixedStructType::Fs_Openbsd_x86_Lastlog => openbsd_x86::LASTLOG_TIMEVALUE_SZ,
×
322
            FixedStructType::Fs_Openbsd_x86_Utmp => openbsd_x86::UTMP_TIMEVALUE_SZ,
×
323
        }
324
    }
1,367✔
325

326
    /// the datetime field as a pair of seconds and microseconds taken from
327
    /// raw bytes
328
    pub fn tv_pair_from_buffer(&self, buffer: &[u8]) -> Option<tv_pair_type> {
1,177✔
329
        defn!("type {:?}", self);
1,177✔
330
        let tv_sec: tv_sec_type;
331
        let tv_usec: tv_usec_type;
332
        let size = self.size_tv();
1,177✔
333
        match self {
1,177✔
334
            FixedStructType::Fs_Freebsd_x8664_Utmpx => {
335
                buffer_to_timeval!(freebsd_x8664::timeval, size, buffer, tv_sec, tv_usec);
×
336
                defo_tv_pair!(tv_sec, tv_usec);
×
337
            }
338
            FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => {
339
                buffer_to_time_t!(linux_arm64aarch64::ll_time_t, size, buffer, tv_sec);
×
340
                tv_usec = 0;
×
341
                defo_tv_pair!(tv_sec, tv_usec);
×
342
            }
343
            FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => {
344
                buffer_to_timeval!(linux_arm64aarch64::timeval, size, buffer, tv_sec, tv_usec);
×
345
                defo_tv_pair!(tv_sec, tv_usec);
×
346
            }
347
            FixedStructType::Fs_Linux_x86_Acct => {
348
                buffer_to_time_t!(linux_x86::b_time_t, size, buffer, tv_sec);
×
349
                tv_usec = 0;
×
350
                defo_tv_pair!(tv_sec, tv_usec);
×
351
            }
352
            FixedStructType::Fs_Linux_x86_Acct_v3 => {
353
                buffer_to_time_t!(linux_x86::b_time_t, size, buffer, tv_sec);
×
354
                tv_usec = 0;
×
355
                defo_tv_pair!(tv_sec, tv_usec);
×
356
            }
357
            FixedStructType::Fs_Linux_x86_Lastlog => {
358
                buffer_to_time_t!(linux_x86::ll_time_t, size, buffer, tv_sec);
7✔
359
                tv_usec = 0;
7✔
360
                defo_tv_pair!(tv_sec, tv_usec);
7✔
361
            }
362
            FixedStructType::Fs_Linux_x86_Utmpx => {
363
                buffer_to_timeval!(linux_x86::__timeval, size, buffer, tv_sec, tv_usec);
1,170✔
364
                defo_tv_pair!(tv_sec, tv_usec);
1,170✔
365
            }
366
            FixedStructType::Fs_Netbsd_x8632_Acct => {
367
                buffer_to_time_t!(netbsd_x8632::time_t, size, buffer, tv_sec);
×
368
                tv_usec = 0;
×
369
                defo_tv_pair!(tv_sec, tv_usec);
×
370
            }
371
            FixedStructType::Fs_Netbsd_x8632_Lastlogx => {
372
                buffer_to_timeval!(netbsd_x8632::timeval, size, buffer, tv_sec, tv_usec);
×
373
                defo_tv_pair!(tv_sec, tv_usec);
×
374
            }
375
            FixedStructType::Fs_Netbsd_x8632_Utmpx => {
376
                buffer_to_timeval!(netbsd_x8632::timeval, size, buffer, tv_sec, tv_usec);
×
377
                defo_tv_pair!(tv_sec, tv_usec);
×
378
            }
379
            FixedStructType::Fs_Netbsd_x8664_Lastlog => {
380
                buffer_to_time_t!(netbsd_x8664::time_t, size, buffer, tv_sec);
×
381
                tv_usec = 0;
×
382
                defo_tv_pair!(tv_sec, tv_usec);
×
383
            }
384
            FixedStructType::Fs_Netbsd_x8664_Lastlogx => {
385
                buffer_to_timeval!(netbsd_x8664::timeval, size, buffer, tv_sec, tv_usec);
×
386
                defo_tv_pair!(tv_sec, tv_usec);
×
387
            }
388
            FixedStructType::Fs_Netbsd_x8664_Utmp => {
389
                buffer_to_time_t!(netbsd_x8664::time_t, size, buffer, tv_sec);
×
390
                tv_usec = 0;
×
391
                defo_tv_pair!(tv_sec, tv_usec);
×
392
            }
393
            FixedStructType::Fs_Netbsd_x8664_Utmpx => {
394
                buffer_to_timeval!(netbsd_x8664::timeval, size, buffer, tv_sec, tv_usec);
×
395
                defo_tv_pair!(tv_sec, tv_usec);
×
396
            }
397
            FixedStructType::Fs_Openbsd_x86_Lastlog => {
398
                buffer_to_time_t!(openbsd_x86::time_t, size, buffer, tv_sec);
×
399
                tv_usec = 0;
×
400
                defo_tv_pair!(tv_sec, tv_usec);
×
401
            }
402
            FixedStructType::Fs_Openbsd_x86_Utmp => {
403
                buffer_to_time_t!(openbsd_x86::time_t, size, buffer, tv_sec);
×
404
                tv_usec = 0;
×
405
                defo_tv_pair!(tv_sec, tv_usec);
×
406
            }
407
        }
408

409
        let tv_pair = tv_pair_type(tv_sec, tv_usec);
1,177✔
410
        defx!("return Some({:?})", tv_pair);
1,177✔
411

412
        Some(tv_pair)
1,177✔
413
    }
1,177✔
414
}
415

416
// listing of specific FixedStruct implementations
417
// all listings should be in alphabetical order
418

419
// BUG: [2024/03/10] the `&CStr` wrappers do not protect against no
420
//      null-termination in the underlying buffer.
421
//      e.g. `freebsd_x8664::utmpx::ut_user()` may include the following field
422
//      `freebsd_x8664::utmpx::ut_line`.
423
//      This only affects debug printing and tests.
424

425
// freebsd_x8664
426

427
/// FixedStruct definitions found on FreeBSD 14.0 amd64 and FreeBSD 13.1 amd64
428
/// (x86_64).
429
#[allow(non_camel_case_types, unused)]
430
pub mod freebsd_x8664 {
431
    use crate::common::FileOffset;
432
    use std::ffi::CStr;
433
    use std::mem::size_of;
434
    use ::memoffset::offset_of;
435
    use ::const_format::assertcp_eq;
436

437
    pub type subseconds_t = std::ffi::c_longlong;
438
    // XXX: use `i64` to satisfy various cross-compilation targets
439
    pub type time_t = i64;
440

441
    // utmpx
442

443
    /// From [`/usr/include/sys/_timeval.h`]
444
    /// 
445
    /// ```C
446
    /// struct timeval {
447
    ///     time_t          tv_sec;         /* seconds */
448
    ///     suseconds_t     tv_usec;        /* and microseconds */
449
    /// };
450
    /// ```
451
    ///
452
    /// [`/usr/include/sys/_timeval.h`]: https://github.com/freebsd/freebsd-src/blob/release/12.4.0/sys/sys/_timeval.h#L46-L52
453
    #[derive(Clone, Copy)]
454
    #[repr(C, align(8))]
455
    #[allow(non_camel_case_types)]
456
    pub struct timeval {
457
        pub tv_sec: time_t,
458
        pub tv_usec: subseconds_t,
459
    }
460

461
    pub const TIMEVAL_SZ: usize = size_of::<timeval>();
462
    assertcp_eq!(TIMEVAL_SZ, 16);
463
    assertcp_eq!(offset_of!(timeval, tv_sec), 0);
464
    assertcp_eq!(offset_of!(timeval, tv_usec), 8);
465

466
    pub const UT_IDSIZE: usize = 8;
467
    pub const UT_USERSIZE: usize = 32;
468
    pub const UT_LINESIZE: usize = 16;
469
    pub const UT_HOSTSIZE: usize = 128;
470

471
    pub type c_char = std::ffi::c_char;
472
    pub type c_short = std::ffi::c_short;
473
    pub type c_ushort = std::ffi::c_ushort;
474
    pub type pid_t = std::ffi::c_int;
475

476
    /// From [`/usr/src/include/utmpx.h`] on FreeBSD 14.0 amd64
477
    ///
478
    /// ```C
479
    /// struct utmpx {
480
    ///     short           ut_type;        /* Type of entry. */
481
    ///     struct timeval  ut_tv;          /* Time entry was made. */
482
    ///     char            ut_id[8];       /* Record identifier. */
483
    ///     pid_t           ut_pid;         /* Process ID. */
484
    ///     char            ut_user[32];    /* User login name. */
485
    ///     char            ut_line[16];    /* Device name. */
486
    /// #if __BSD_VISIBLE
487
    ///     char            ut_host[128];   /* Remote hostname. */
488
    /// #else
489
    ///     char            __ut_host[128];
490
    /// #endif
491
    ///     char            __ut_spare[64];
492
    /// };
493
    /// ```
494
    ///
495
    /// Also see [FreeBSD 12.4 `utmpx.h`].
496
    /// Also see [_Replacing utmp.h with utmpx.h_].
497
    ///
498
    /// ---
499
    ///
500
    ///
501
    /// ```text
502
    /// timeval               sizeof  16
503
    /// timeval.tv_sec   @  0 sizeof   8
504
    /// timeval.tv_usec  @  8 sizeof   8
505
    ///
506
    /// utmpx                   sizeof 280
507
    /// utmpx.ut_type      @  0 sizeof   2
508
    /// utmpx.ut_tv        @  8 sizeof  16
509
    /// utmpx.ut_tv.tv_sec @  8 sizeof   8
510
    /// utmpx.ut_tv.tv_usec@ 16 sizeof   8
511
    /// utmpx.ut_id        @ 24 sizeof   8
512
    /// utmpx.ut_pid       @ 32 sizeof   4
513
    /// utmpx.ut_user      @ 36 sizeof  32
514
    /// utmpx.ut_line      @ 68 sizeof  16
515
    /// utmpx.ut_host      @ 84 sizeof 128
516
    /// ```
517
    ///
518
    /// [`/usr/src/include/utmpx.h`]: https://cgit.freebsd.org/src/tree/include/utmpx.h?h=stable/14
519
    /// [FreeBSD 12.4 `utmpx.h`]: https://github.com/freebsd/freebsd-src/blob/release/12.4.0/include/utmpx.h#L43-L56
520
    /// [_Replacing utmp.h with utmpx.h_]: https://lists.freebsd.org/pipermail/freebsd-arch/2010-January/009816.html
521
    #[derive(Clone, Copy)]
522
    #[allow(non_camel_case_types)]
523
    #[repr(C, align(8))]
524
    pub struct utmpx {
525
        pub ut_type: c_short,
526
        pub __gap1: [u8; 6],
527
        pub ut_tv: timeval,
528
        pub ut_id: [c_char; UT_IDSIZE],
529
        pub ut_pid: pid_t,
530
        pub ut_user: [c_char; UT_USERSIZE],
531
        pub ut_line: [c_char; UT_LINESIZE],
532
        pub ut_host: [c_char; UT_HOSTSIZE],
533
        pub __ut_spare: [c_char; 64],
534
    }
535

536
    pub const UTMPX_SZ: usize = size_of::<utmpx>();
537
    pub const UTMPX_SZ_FO: FileOffset = UTMPX_SZ as FileOffset;
538
    pub const UTMPX_TIMEVALUE_OFFSET: usize = offset_of!(utmpx, ut_tv);
539
    pub const UTMPX_TIMEVALUE_SZ: usize = TIMEVAL_SZ;
540
    pub const UTMPX_TIMEVALUE_OFFSET_TV_SEC: usize = UTMPX_TIMEVALUE_OFFSET + offset_of!(timeval, tv_sec);
541
    pub const UTMPX_TIMEVALUE_OFFSET_TV_USEC: usize = UTMPX_TIMEVALUE_OFFSET + offset_of!(timeval, tv_usec);
542
    assertcp_eq!(UTMPX_SZ, 280);
543
    assertcp_eq!(offset_of!(utmpx, ut_type), 0);
544
    assertcp_eq!(offset_of!(utmpx, __gap1), 2);
545
    assertcp_eq!(offset_of!(utmpx, ut_tv), 8);
546
    assertcp_eq!(offset_of!(utmpx, ut_id), 24);
547
    assertcp_eq!(offset_of!(utmpx, ut_pid), 32);
548
    assertcp_eq!(offset_of!(utmpx, ut_user), 36);
549
    assertcp_eq!(offset_of!(utmpx, ut_line), 68);
550
    assertcp_eq!(offset_of!(utmpx, ut_host), 84);
551
    assertcp_eq!(offset_of!(utmpx, __ut_spare), 212);
552

553
    /// Helpers for use in `fmt::Debug` trait.
554
    impl utmpx {
555
        pub fn ut_id(&self) -> &CStr {
2✔
556
            unsafe { CStr::from_ptr(self.ut_id[..UT_IDSIZE].as_ptr()) }
2✔
557
        }
2✔
558
        pub fn ut_user(&self) -> &CStr {
6✔
559
            unsafe { CStr::from_ptr(self.ut_user[..UT_USERSIZE].as_ptr()) }
6✔
560
        }
6✔
561
        pub fn ut_line(&self) -> &CStr {
5✔
562
            unsafe { CStr::from_ptr(self.ut_line[..UT_LINESIZE].as_ptr()) }
5✔
563
        }
5✔
564
        pub fn ut_host(&self) -> &CStr {
5✔
565
            unsafe { CStr::from_ptr(self.ut_host[..UT_HOSTSIZE].as_ptr()) }
5✔
566
        }
5✔
567
    }
568

569
    /// From [`include/utmpx.h`], FreeBSD 12.4
570
    /// ```C
571
    /// #define        EMPTY                0        /* No valid user accounting information. */
572
    /// #define        BOOT_TIME        1        /* Time of system boot. */
573
    /// #define        OLD_TIME        2        /* Time when system clock changed. */
574
    /// #define        NEW_TIME        3        /* Time after system clock changed. */
575
    /// #define        USER_PROCESS        4        /* A process. */
576
    /// #define        INIT_PROCESS        5        /* A process spawned by the init process. */
577
    /// #define        LOGIN_PROCESS        6        /* The session leader of a logged-in user. */
578
    /// #define        DEAD_PROCESS        7        /* A session leader who has exited. */
579
    /// #if __BSD_VISIBLE
580
    /// #define        SHUTDOWN_TIME        8        /* Time of system shutdown. */
581
    /// #endif
582
    /// 
583
    /// #if __BSD_VISIBLE
584
    /// #define        UTXDB_ACTIVE        0        /* Active login sessions. */
585
    /// #define        UTXDB_LASTLOGIN        1        /* Last login sessions. */
586
    /// #define        UTXDB_LOG        2        /* Log indexed by time. */
587
    /// #endif
588
    /// ```
589
    ///
590
    /// [`include/utmpx.h`]: https://github.com/freebsd/freebsd-src/blob/release/12.4.0/include/utmpx.h#L58C1-L74C7
591
    pub const UT_TYPES: [c_short; 9] = [
592
        0, 1, 2, 3, 4, 5, 6, 7, 8
593
    ];
594
}
595

596
/// FixedStruct definitions found on Linux running on ARM64 (aarch64)
597
/// architecture.
598
#[allow(non_camel_case_types)]
599
pub mod linux_arm64aarch64 {
600
    use crate::common::FileOffset;
601
    use std::ffi::CStr;
602
    use std::mem::size_of;
603
    use ::const_format::assertcp_eq;
604
    use ::memoffset::offset_of;
605

606
    pub type c_char = std::ffi::c_char;
607
    pub type c_short = std::ffi::c_short;
608
    pub type ll_time_t = std::ffi::c_longlong;
609
    pub type pid_t = std::ffi::c_int;
610
    pub type suseconds_t = std::ffi::c_longlong;
611

612
    // timeval
613

614
    /// ```text
615
    /// timeval               sizeof  16
616
    /// timeval.tv_sec   @  0 sizeof   8
617
    /// timeval.tv_usec  @  8 sizeof   8
618
    /// ```
619
    #[derive(Clone, Copy)]
620
    #[repr(C, align(8))]
621
    #[allow(non_camel_case_types)]
622
    pub struct timeval {
623
        pub tv_sec: i64,
624
        pub tv_usec: i64,
625
    }
626

627
    pub const TIMEVAL_SZ: usize = size_of::<timeval>();
628
    assertcp_eq!(TIMEVAL_SZ, 16);
629
    assertcp_eq!(offset_of!(timeval, tv_sec), 0);
630
    assertcp_eq!(offset_of!(timeval, tv_usec), 8);
631

632
    pub const UT_LINESIZE: usize = 32;
633
    pub const UT_IDSIZE: usize = 4;
634
    pub const UT_NAMESIZE: usize = 32;
635
    pub const UT_USERSIZE: usize = 32;
636
    pub const UT_HOSTSIZE: usize = 256;
637

638
    // lastlog
639

640
    /// ```text
641
    /// lastlog               sizeof 296
642
    /// lastlog.ll_time  @  0 sizeof   8
643
    /// lastlog.ll_line  @  8 sizeof  32
644
    /// lastlog.ll_host  @ 40 sizeof 256
645
    /// ```
646
    #[derive(Clone, Copy)]
647
    #[repr(C, align(8))]
648
    #[allow(non_camel_case_types)]
649
    pub struct lastlog {
650
        pub ll_time: ll_time_t,
651
        pub ll_line: [c_char; UT_LINESIZE],
652
        pub ll_host: [c_char; UT_HOSTSIZE],
653
    }
654

655
    impl lastlog {
656
        pub fn ll_line(&self) -> &CStr {
5✔
657
            unsafe { CStr::from_ptr(self.ll_line.as_ptr()) }
5✔
658
        }
5✔
659
        pub fn ll_host(&self) -> &CStr {
5✔
660
            unsafe { CStr::from_ptr(self.ll_host.as_ptr()) }
5✔
661
        }
5✔
662
    }
663

664
    pub const LASTLOG_SZ: usize = size_of::<lastlog>();
665
    pub const LASTLOG_SZ_FO: FileOffset = LASTLOG_SZ as FileOffset;
666
    pub const LASTLOG_TIMEVALUE_OFFSET: usize = offset_of!(lastlog, ll_time);
667
    pub const LASTLOG_TIMEVALUE_SZ: usize = size_of::<ll_time_t>();
668
    assertcp_eq!(LASTLOG_SZ, 296);
669
    assertcp_eq!(offset_of!(lastlog, ll_time), 0);
670
    assertcp_eq!(offset_of!(lastlog, ll_line), 8);
671
    assertcp_eq!(offset_of!(lastlog, ll_host), 40);
672

673
    // utmp == utmpx
674

675
    /// From [`man utmpx`]
676
    ///
677
    /// ```C
678
    /// /* Values for ut_type field, below */
679
    ///
680
    /// #define EMPTY         0 /* Record does not contain valid info
681
    /// (formerly known as UT_UNKNOWN on Linux) */
682
    /// #define RUN_LVL       1 /* Change in system run-level (see
683
    /// init(8)) */
684
    /// #define BOOT_TIME     2 /* Time of system boot (in ut_tv) */
685
    /// #define NEW_TIME      3 /* Time after system clock change
686
    /// (in ut_tv) */
687
    /// #define OLD_TIME      4 /* Time before system clock change
688
    /// (in ut_tv) */
689
    /// #define INIT_PROCESS  5 /* Process spawned by init(8) */
690
    /// #define LOGIN_PROCESS 6 /* Session leader process for user login */
691
    /// #define USER_PROCESS  7 /* Normal process */
692
    /// #define DEAD_PROCESS  8 /* Terminated process */
693
    /// #define ACCOUNTING    9 /* Not implemented */
694
    ///
695
    /// #define UT_LINESIZE      32
696
    /// #define UT_NAMESIZE      32
697
    /// #define UT_HOSTSIZE     256
698
    ///
699
    /// struct exit_status {          /* Type for ut_exit, below */
700
    /// short int e_termination;      /* Process termination status */
701
    /// short int e_exit;             /* Process exit status */
702
    /// };
703
    ///
704
    /// struct utmp {
705
    /// short   ut_type;              /* Type of record */
706
    /// pid_t   ut_pid;               /* PID of login process */
707
    /// char    ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */
708
    /// char    ut_id[4];             /* Terminal name suffix,
709
    ///                                  or inittab(5) ID */
710
    /// char    ut_user[UT_NAMESIZE]; /* Username */
711
    /// char    ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or
712
    ///                                  kernel version for run-level
713
    ///                                  messages */
714
    /// struct  exit_status ut_exit;  /* Exit status of a process
715
    ///                                  marked as DEAD_PROCESS; not
716
    ///                                  used by Linux init(8) */
717
    /// /* The ut_session and ut_tv fields must be the same size when
718
    /// compiled 32- and 64-bit.  This allows data files and shared
719
    /// memory to be shared between 32- and 64-bit applications. */
720
    /// #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
721
    /// int32_t ut_session;           /* Session ID (getsid(2)),
722
    ///                                  used for windowing */
723
    /// struct {
724
    ///     int32_t tv_sec;           /* Seconds */
725
    ///     int32_t tv_usec;          /* Microseconds */
726
    /// } ut_tv;                      /* Time entry was made */
727
    /// #else
728
    /// long   ut_session;           /* Session ID */
729
    /// struct timeval ut_tv;        /* Time entry was made */
730
    /// #endif
731
    ///
732
    /// int32_t ut_addr_v6[4];        /* Internet address of remote
733
    ///                                  host; IPv4 address uses
734
    ///                                  just ut_addr_v6[0] */
735
    /// char __unused[20];            /* Reserved for future use */
736
    /// };
737
    ///
738
    /// /* Backward compatibility hacks */
739
    /// #define ut_name ut_user
740
    /// #ifndef _NO_UT_TIME
741
    /// #define ut_time ut_tv.tv_sec
742
    /// #endif
743
    /// #define ut_xtime ut_tv.tv_sec
744
    /// #define ut_addr ut_addr_v6[0]
745
    /// ```
746
    ///
747
    /// ---
748
    ///
749
    /// ```text
750
    /// utmpx                   sizeof 400
751
    /// utmpx.ut_type      @  0 sizeof   2
752
    /// utmpx.ut_pid       @  4 sizeof   4
753
    /// utmpx.ut_line      @  8 sizeof  32
754
    /// utmpx.ut_id        @ 40 sizeof   4
755
    /// utmpx.ut_user      @ 44 sizeof  32
756
    /// utmpx.ut_host      @ 76 sizeof 256
757
    /// utmpx.ut_exit      @332 sizeof   4
758
    /// utmpx.ut_session   @336 sizeof   8
759
    /// utmpx.ut_tv        @344 sizeof  16
760
    /// utmpx.ut_tv.tv_sec @344 sizeof   8
761
    /// utmpx.ut_tv.tv_usec@352 sizeof   8
762
    /// utmpx.ut_addr      @360 sizeof   4
763
    /// utmpx.ut_addr_v6   @360 sizeof  16
764
    /// ```
765
    ///
766
    /// [`man utmpx`]: https://linux.die.net/man/5/utmpx
767
    #[derive(Clone, Copy)]
768
    #[repr(C, align(4))]
769
    #[allow(non_camel_case_types)]
770
    pub struct utmpx {
771
        pub ut_type: c_short,
772
        pub ut_pid: pid_t,
773
        pub ut_line: [c_char; UT_LINESIZE],
774
        pub ut_id: [c_char; UT_IDSIZE],
775
        pub ut_user: [c_char; UT_NAMESIZE],
776
        pub ut_host: [c_char; UT_HOSTSIZE],
777
        pub ut_exit: i32,
778
        pub ut_session: i64,
779
        pub ut_tv: timeval,
780
        pub ut_addr_v6: [i32; 4],
781
        pub __glibc_reserved: [c_char; 20],
782
    }
783

784
    impl utmpx {
785
        pub fn ut_line(&self) -> &CStr {
5✔
786
            unsafe { CStr::from_ptr(self.ut_line.as_ptr()) }
5✔
787
        }
5✔
788
        pub fn ut_id(&self) -> &CStr {
2✔
789
            unsafe { CStr::from_ptr(self.ut_id.as_ptr()) }
2✔
790
        }
2✔
791
        pub fn ut_user(&self) -> &CStr {
5✔
792
            unsafe { CStr::from_ptr(self.ut_user.as_ptr()) }
5✔
793
        }
5✔
794
        pub fn ut_host(&self) -> &CStr {
5✔
795
            unsafe { CStr::from_ptr(self.ut_host.as_ptr()) }
5✔
796
        }
5✔
797
    }
798

799
    pub const UTMPX_SZ: usize = size_of::<utmpx>();
800
    pub const UTMPX_SZ_FO: FileOffset = UTMPX_SZ as FileOffset;
801
    pub const UTMPX_TIMEVALUE_OFFSET: usize = offset_of!(utmpx, ut_tv);
802
    pub const UTMPX_TIMEVALUE_SZ: usize = TIMEVAL_SZ;
803
    assertcp_eq!(UTMPX_SZ, 400);
804
    assertcp_eq!(offset_of!(utmpx, ut_type), 0);
805
    assertcp_eq!(offset_of!(utmpx, ut_pid), 4);
806
    assertcp_eq!(offset_of!(utmpx, ut_line), 8);
807
    assertcp_eq!(offset_of!(utmpx, ut_id), 40);
808
    assertcp_eq!(offset_of!(utmpx, ut_user), 44);
809
    assertcp_eq!(offset_of!(utmpx, ut_host), 76);
810
    assertcp_eq!(offset_of!(utmpx, ut_exit), 332);
811
    assertcp_eq!(offset_of!(utmpx, ut_session), 336);
812
    assertcp_eq!(offset_of!(utmpx, ut_tv), 344);
813
    assertcp_eq!(offset_of!(utmpx, ut_addr_v6), 360);
814
    assertcp_eq!(offset_of!(utmpx, __glibc_reserved), 376);
815

816
    /// From [`utmpx.h`], Linux 6.1
817
    /// ```C
818
    /// #define EMPTY           0
819
    /// #define RUN_LVL         1
820
    /// #define BOOT_TIME       2
821
    /// #define NEW_TIME        3
822
    /// #define OLD_TIME        4
823
    /// #define INIT_PROCESS    5
824
    /// #define LOGIN_PROCESS   6
825
    /// #define USER_PROCESS    7
826
    /// #define DEAD_PROCESS    8
827
    /// ```
828
    ///
829
    /// [`utmpx.h`]: https://elixir.bootlin.com/musl/latest/source/include/utmpx.h
830
    pub const UT_TYPES: [c_short; 9] = [
831
        0, 1, 2, 3, 4, 5, 6, 7, 8
832
    ];
833
}
834

835
/// FixedStruct definitions found in `lastlog.h`, `utmp.h`, `utmpx.h`
836
/// from GNU glibc for Linux, architectures amd64 (x86_64), i686 (x86_32),
837
/// ARM6 (aarch64), and RISC-V (riscv64).
838
///
839
/// Found on Ubuntu 22.04 amd64 (x86_64) Linux 5.15, in files:
840
/// * `/usr/include/lastlog.h`
841
/// * `/usr/include/utmp.h`
842
/// * `/usr/include/utmpx.h`
843
/// * `/usr/include/x86_64-linux-gnu/bits/utmp.h`
844
/// * `/usr/include/x86_64-linux-gnu/bits/utmpx.h`
845
///
846
/// Confirmed the sizes and offsets are the same on:
847
/// * CentOS 7 amd64 (x86_64) Linux 3.10
848
/// * Ubuntu 16 i686 (x86_32) Linux 4.4
849
/// * Debian 11 ARM6 (aarch64) Linux 6.1
850
/// * Debian 13 RISC-V (riscv64) Linux 6.1
851
///
852
/// However, `struct timeval` differs on in size on x86_64/32 and ARM6. Yet the
853
/// `utmpx.ut_tv`, which is sometimes defined in-place and sometimes typed as a
854
/// `struct timeval` or `struct __timeval`, is the same size on both.
855
/// From the [code comment in `utmpx.h`]:
856
/// ```C
857
/// /* The fields ut_session and ut_tv must be the same size when compiled
858
///    32- and 64-bit.  This allows files and shared memory to be shared
859
///    between 32- and 64-bit applications.  */
860
/// ```
861
///
862
/// The `utmp` struct is exactly the same as the `utmpx` struct except for a few
863
/// different names. This mod defines `utmpx` and not `utmp`.
864
///
865
/// [code comment in `utmpx.h`]: https://elixir.bootlin.com/glibc/latest/source/sysdeps/gnu/bits/utmpx.h
866
#[allow(non_camel_case_types)]
867
pub mod linux_x86 {
868
    use crate::common::FileOffset;
869
    use std::ffi::CStr;
870
    use std::mem::size_of;
871
    use ::memoffset::offset_of;
872
    use ::const_format::assertcp_eq;
873

874
    pub type b_time_t = std::ffi::c_uint;
875
    pub type c_char = std::ffi::c_char;
876
    pub type c_short = std::ffi::c_short;
877
    pub type comp_t = std::ffi::c_ushort;
878
    pub type ll_time_t = std::ffi::c_int;
879
    pub type pid_t = std::ffi::c_int;
880
    pub type suseconds_t = std::ffi::c_longlong;
881
    pub type uint16_t = std::ffi::c_ushort;
882

883
    pub const PATH_ACCT: &str = "/var/log/account/acct";
884
    pub const PATH_PACCT: &str = "/var/log/account/pacct";
885

886
    pub const ACCT_COMM: usize = 16;
887

888
    pub const AFORK: c_char = 0x01;
889
    pub const ASU: c_char = 0x02;
890
    pub const ACOMPAT: c_char = 0x04;
891
    pub const ACORE: c_char = 0x08;
892
    pub const AXSIG: c_char = 0x10;
893

894
    pub const AC_FLAGS_MASK: c_char = AFORK | ASU | ACOMPAT | ACORE | AXSIG;
895

896
    /// from [`/usr/include/uapi/linux/acct.h`] on Ubuntu 22.04
897
    ///
898
    /// [`/usr/include/uapi/linux/acct.h`]: https://github.com/torvalds/linux/blob/v5.15/include/uapi/linux/acct.h#L75-L101
899
    ///
900
    /// ```C
901
    /// struct acct
902
    /// {
903
    ///   char ac_flag;                 /* Flags.  */
904
    ///   uint16_t ac_uid;              /* Real user ID.  */
905
    ///   uint16_t ac_gid;              /* Real group ID.  */
906
    ///   uint16_t ac_tty;              /* Controlling terminal.  */
907
    ///   uint32_t ac_btime;            /* Beginning time.  */
908
    ///   comp_t ac_utime;              /* User time.  */
909
    ///   comp_t ac_stime;              /* System time.  */
910
    ///   comp_t ac_etime;              /* Elapsed time.  */
911
    ///   comp_t ac_mem;                /* Average memory usage.  */
912
    ///   comp_t ac_io;                 /* Chars transferred.  */
913
    ///   comp_t ac_rw;                 /* Blocks read or written.  */
914
    ///   comp_t ac_minflt;             /* Minor pagefaults.  */
915
    ///   comp_t ac_majflt;             /* Major pagefaults.  */
916
    ///   comp_t ac_swaps;              /* Number of swaps.  */
917
    ///   uint32_t ac_exitcode;         /* Process exitcode.  */
918
    ///   char ac_comm[ACCT_COMM+1];    /* Command name.  */
919
    ///   char ac_pad[10];              /* Padding bytes.  */
920
    /// }; 
921
    ///
922
    /// #define AFORK                0x01        /* ... executed fork, but did not exec */
923
    /// #define ASU                0x02        /* ... used super-user privileges */
924
    /// #define ACOMPAT                0x04        /* ... used compatibility mode (VAX only not used) */
925
    /// #define ACORE                0x08        /* ... dumped core */
926
    /// #define AXSIG                0x10        /* ... was killed by a signal */
927
    /// ```
928
    ///
929
    /// ---
930
    ///
931
    /// ```text
932
    /// acct                 sizeof  64
933
    /// acct.ac_flag    @  0 sizeof   1
934
    /// acct.ac_uid     @  2 sizeof   2
935
    /// acct.ac_gid     @  4 sizeof   2
936
    /// acct.ac_tty     @  6 sizeof   2
937
    /// acct.ac_btime   @  8 sizeof   4
938
    /// acct.ac_utime   @ 12 sizeof   2
939
    /// acct.ac_stime   @ 14 sizeof   2
940
    /// acct.ac_etime   @ 16 sizeof   2
941
    /// acct.ac_mem     @ 18 sizeof   2
942
    /// acct.ac_io      @ 20 sizeof   2
943
    /// acct.ac_rw      @ 22 sizeof   2
944
    /// acct.ac_exitcode@ 32 sizeof   4
945
    /// acct.ac_comm    @ 36 sizeof  17
946
    /// ```
947
    #[derive(Clone, Copy)]
948
    #[repr(C, align(2))]
949
    #[allow(non_camel_case_types)]
950
    pub struct acct {
951
        pub ac_flag: c_char,
952
        pub ac_uid: uint16_t,
953
        pub ac_gid: uint16_t,
954
        pub ac_tty: uint16_t,
955
        pub ac_btime: b_time_t,
956
        pub ac_utime: comp_t,
957
        pub ac_stime: comp_t,
958
        pub ac_etime: comp_t,
959
        pub ac_mem: comp_t,
960
        pub ac_io: comp_t,
961
        pub ac_rw: comp_t,
962
        pub ac_minflt: comp_t,
963
        pub ac_majflt: comp_t,
964
        pub ac_swaps: comp_t,
965
        pub ac_exitcode: u32,
966
        pub ac_comm: [c_char; ACCT_COMM + 1],
967
        pub ac_pad: [c_char; 10],
968
    }
969

970
    pub const ACCT_SZ: usize = size_of::<acct>();
971
    pub const ACCT_SZ_FO: FileOffset = ACCT_SZ as FileOffset;
972
    pub const ACCT_TIMEVALUE_OFFSET: usize = offset_of!(acct, ac_btime);
973
    pub const ACCT_TIMEVALUE_SZ: usize = size_of::<b_time_t>();
974
    assertcp_eq!(ACCT_SZ, 64);
975
    assertcp_eq!(offset_of!(acct, ac_flag), 0);
976
    assertcp_eq!(offset_of!(acct, ac_uid), 2);
977
    assertcp_eq!(offset_of!(acct, ac_gid), 4);
978
    assertcp_eq!(offset_of!(acct, ac_tty), 6);
979
    assertcp_eq!(offset_of!(acct, ac_btime), 8);
980
    assertcp_eq!(offset_of!(acct, ac_utime), 12);
981
    assertcp_eq!(offset_of!(acct, ac_stime), 14);
982
    assertcp_eq!(offset_of!(acct, ac_etime), 16);
983
    assertcp_eq!(offset_of!(acct, ac_mem), 18);
984
    assertcp_eq!(offset_of!(acct, ac_io), 20);
985
    assertcp_eq!(offset_of!(acct, ac_rw), 22);
986
    assertcp_eq!(offset_of!(acct, ac_minflt), 24);
987
    assertcp_eq!(offset_of!(acct, ac_majflt), 26);
988
    assertcp_eq!(offset_of!(acct, ac_swaps), 28);
989
    assertcp_eq!(offset_of!(acct, ac_exitcode), 32);
990
    assertcp_eq!(offset_of!(acct, ac_comm), 36);
991
    assertcp_eq!(offset_of!(acct, ac_pad), 53);
992

993
    impl acct {
994
        pub fn ac_comm(&self) -> &CStr {
585✔
995
            unsafe { CStr::from_ptr(self.ac_comm.as_ptr()) }
585✔
996
        }
585✔
997
    }
998

999
    /// From [`/usr/include/uapi/linux/acct.h`] on Ubuntu 22.04
1000
    ///
1001
    /// [`/usr/include/uapi/linux/acct.h`]: https://github.com/torvalds/linux/blob/v5.15/include/uapi/linux/acct.h#L75-L101
1002
    ///
1003
    /// ```C
1004
    /// struct acct_v3
1005
    /// {
1006
    ///         char            ac_flag;                /* Flags */
1007
    ///         char            ac_version;             /* Always set to ACCT_VERSION */
1008
    ///         __u16           ac_tty;                 /* Control Terminal */
1009
    ///         __u32           ac_exitcode;            /* Exitcode */
1010
    ///         __u32           ac_uid;                 /* Real User ID */
1011
    ///         __u32           ac_gid;                 /* Real Group ID */
1012
    ///         __u32           ac_pid;                 /* Process ID */
1013
    ///         __u32           ac_ppid;                /* Parent Process ID */
1014
    ///         /* __u32 range means times from 1970 to 2106 */
1015
    ///         __u32           ac_btime;               /* Process Creation Time */
1016
    ///         float           ac_etime;               /* Elapsed Time */
1017
    ///         comp_t          ac_utime;               /* User Time */
1018
    ///         comp_t          ac_stime;               /* System Time */
1019
    ///         comp_t          ac_mem;                 /* Average Memory Usage */
1020
    ///         comp_t          ac_io;                  /* Chars Transferred */
1021
    ///         comp_t          ac_rw;                  /* Blocks Read or Written */
1022
    ///         comp_t          ac_minflt;              /* Minor Pagefaults */
1023
    ///         comp_t          ac_majflt;              /* Major Pagefaults */
1024
    ///         comp_t          ac_swaps;               /* Number of Swaps */
1025
    ///         char            ac_comm[ACCT_COMM];     /* Command Name */
1026
    /// };
1027
    ///
1028
    /// #define AFORK                0x01        /* ... executed fork, but did not exec */
1029
    /// #define ASU                0x02        /* ... used super-user privileges */
1030
    /// #define ACOMPAT                0x04        /* ... used compatibility mode (VAX only not used) */
1031
    /// #define ACORE                0x08        /* ... dumped core */
1032
    /// #define AXSIG                0x10        /* ... was killed by a signal */
1033
    /// ```
1034
    ///
1035
    /// ---
1036
    ///
1037
    /// ```text
1038
    /// acct_v3                  sizeof  64
1039
    /// acct_v3.ac_flag     @  0 sizeof   1
1040
    /// acct_v3.ac_version  @  1 sizeof   1
1041
    /// acct_v3.ac_tty      @  2 sizeof   2
1042
    /// acct_v3.ac_exitcode @  4 sizeof   4
1043
    /// acct_v3.ac_uid      @  8 sizeof   4
1044
    /// acct_v3.ac_gid      @ 12 sizeof   4
1045
    /// acct_v3.ac_pid      @ 16 sizeof   4
1046
    /// acct_v3.ac_ppid     @ 20 sizeof   4
1047
    /// acct_v3.ac_btime    @ 24 sizeof   4
1048
    /// acct_v3.ac_etime    @ 28 sizeof   4
1049
    /// acct_v3.ac_utime    @ 32 sizeof   2
1050
    /// acct_v3.ac_stime    @ 34 sizeof   2
1051
    /// acct_v3.ac_mem      @ 36 sizeof   2
1052
    /// acct_v3.ac_io       @ 38 sizeof   2
1053
    /// acct_v3.ac_rw       @ 40 sizeof   2
1054
    /// acct_v3.ac_minflt   @ 42 sizeof   2
1055
    /// acct_v3.ac_majflt   @ 44 sizeof   2
1056
    /// acct_v3.ac_swaps    @ 46 sizeof   2
1057
    /// acct_v3.ac_comm     @ 48 sizeof  16
1058
    /// ```
1059
    #[derive(Clone, Copy)]
1060
    #[repr(C, align(4))]
1061
    #[allow(non_camel_case_types)]
1062
    pub struct acct_v3 {
1063
        pub ac_flag: c_char,
1064
        pub ac_version: c_char,
1065
        pub ac_tty: u16,
1066
        pub ac_exitcode: u32,
1067
        pub ac_uid: u32,
1068
        pub ac_gid: u32,
1069
        pub ac_pid: u32,
1070
        pub ac_ppid: u32,
1071
        pub ac_btime: b_time_t,
1072
        pub ac_etime: f32,
1073
        pub ac_utime: comp_t,
1074
        pub ac_stime: comp_t,
1075
        pub ac_mem: comp_t,
1076
        pub ac_io: comp_t,
1077
        pub ac_rw: comp_t,
1078
        pub ac_minflt: comp_t,
1079
        pub ac_majflt: comp_t,
1080
        pub ac_swaps: comp_t,
1081
        pub ac_comm: [c_char; ACCT_COMM],
1082
    }
1083
    // XXX: not handling ACCT_BYTEORDER which changes the byte order
1084
    //      of the file
1085

1086
    pub const ACCT_V3_SZ: usize = size_of::<acct_v3>();
1087
    pub const ACCT_V3_SZ_FO: FileOffset = ACCT_V3_SZ as FileOffset;
1088
    pub const ACCT_V3_TIMEVALUE_OFFSET: usize = offset_of!(acct_v3, ac_btime);
1089
    pub const ACCT_V3_TIMEVALUE_SZ: usize = size_of::<b_time_t>();
1090
    assertcp_eq!(ACCT_V3_SZ, 64);
1091
    assertcp_eq!(offset_of!(acct_v3, ac_flag), 0);
1092
    assertcp_eq!(offset_of!(acct_v3, ac_version), 1);
1093
    assertcp_eq!(offset_of!(acct_v3, ac_tty), 2);
1094
    assertcp_eq!(offset_of!(acct_v3, ac_exitcode), 4);
1095
    assertcp_eq!(offset_of!(acct_v3, ac_uid), 8);
1096
    assertcp_eq!(offset_of!(acct_v3, ac_gid), 12);
1097
    assertcp_eq!(offset_of!(acct_v3, ac_pid), 16);
1098
    assertcp_eq!(offset_of!(acct_v3, ac_ppid), 20);
1099
    assertcp_eq!(offset_of!(acct_v3, ac_btime), 24);
1100
    assertcp_eq!(offset_of!(acct_v3, ac_etime), 28);
1101
    assertcp_eq!(offset_of!(acct_v3, ac_utime), 32);
1102
    assertcp_eq!(offset_of!(acct_v3, ac_stime), 34);
1103
    assertcp_eq!(offset_of!(acct_v3, ac_mem), 36);
1104
    assertcp_eq!(offset_of!(acct_v3, ac_io), 38);
1105
    assertcp_eq!(offset_of!(acct_v3, ac_rw), 40);
1106
    assertcp_eq!(offset_of!(acct_v3, ac_minflt), 42);
1107
    assertcp_eq!(offset_of!(acct_v3, ac_majflt), 44);
1108
    assertcp_eq!(offset_of!(acct_v3, ac_swaps), 46);
1109
    assertcp_eq!(offset_of!(acct_v3, ac_comm), 48);
1110

1111
    impl acct_v3 {
1112
        pub fn ac_comm(&self) -> &CStr {
584✔
1113
            unsafe { CStr::from_ptr(self.ac_comm.as_ptr()) }
584✔
1114
        }
584✔
1115
    }
1116

1117
    // lastlog
1118

1119
    pub const UT_LINESIZE: usize = 32;
1120
    pub const UT_IDSIZE: usize = 4;
1121
    pub const UT_NAMESIZE: usize = 32;
1122
    pub const UT_USERSIZE: usize = 32;
1123
    pub const UT_HOSTSIZE: usize = 256;
1124

1125
    /// ```text
1126
    /// lastlog               sizeof 292
1127
    /// lastlog.ll_time  @  0 sizeof   4
1128
    /// lastlog.ll_line  @  4 sizeof  32
1129
    /// lastlog.ll_host  @ 36 sizeof 256
1130
    /// ```
1131
    #[derive(Clone, Copy)]
1132
    #[repr(C, align(4))]
1133
    #[allow(non_camel_case_types)]
1134
    pub struct lastlog {
1135
        pub ll_time: ll_time_t,
1136
        pub ll_line: [c_char; UT_LINESIZE],
1137
        pub ll_host: [c_char; UT_HOSTSIZE],
1138
    }
1139

1140
    pub const LASTLOG_SZ: usize = size_of::<lastlog>();
1141
    pub const LASTLOG_SZ_FO: FileOffset = LASTLOG_SZ as FileOffset;
1142
    pub const LASTLOG_TIMEVALUE_OFFSET: usize = offset_of!(lastlog, ll_time);
1143
    pub const LASTLOG_TIMEVALUE_SZ: usize = size_of::<ll_time_t>();
1144
    assertcp_eq!(LASTLOG_SZ, 292);
1145
    assertcp_eq!(offset_of!(lastlog, ll_time), 0);
1146
    assertcp_eq!(offset_of!(lastlog, ll_line), 4);
1147
    assertcp_eq!(offset_of!(lastlog, ll_host), 36);
1148

1149
    impl lastlog {
1150
        pub fn ll_line(&self) -> &CStr {
26✔
1151
            unsafe { CStr::from_ptr(self.ll_line.as_ptr()) }
26✔
1152
        }
26✔
1153
        pub fn ll_host(&self) -> &CStr {
26✔
1154
            unsafe { CStr::from_ptr(self.ll_host.as_ptr()) }
26✔
1155
        }
26✔
1156
    }
1157

1158
    // utmp
1159

1160
    /// `utmp` == `utmpx` on this platform
1161
    ///
1162
    /// Strangely, the `timeval` on x86_64/32 is sizeof 16 and on ARM6 is
1163
    /// sizeof 8. Yet the `tutmpx.ut_tv`, sometimes typed as a  `__timeval`,
1164
    /// is sizeof 8 on both.
1165
    /// So this `__timeval` is sized to 8 so the `utmp` is the correct size.
1166
    ///
1167
    /// ```text
1168
    /// timeval               sizeof   8
1169
    /// timeval.tv_sec   @  0 sizeof   4
1170
    /// timeval.tv_usec  @  4 sizeof   4
1171
    /// ```
1172
    #[derive(Clone, Copy)]
1173
    #[repr(C, align(4))]
1174
    #[allow(non_camel_case_types)]
1175
    pub struct __timeval {
1176
        pub tv_sec: i32,
1177
        pub tv_usec: i32,
1178
    }
1179
    
1180
    pub const __TIMEVAL_SZ: usize = size_of::<__timeval>();
1181
    assertcp_eq!(__TIMEVAL_SZ, 8);
1182
    assertcp_eq!(offset_of!(__timeval, tv_sec), 0);
1183
    assertcp_eq!(offset_of!(__timeval, tv_usec), 4);
1184

1185
    #[derive(Clone, Copy)]
1186
    #[repr(C, align(2))]
1187
    #[allow(non_camel_case_types)]
1188
    pub struct __exit_status {
1189
        pub e_termination: i16,
1190
        pub e_exit: i16,
1191
    }
1192

1193
    pub const __EXIT_STATUS: usize = size_of::<__exit_status>();
1194
    assertcp_eq!(__EXIT_STATUS, 4);
1195
    assertcp_eq!(offset_of!(__exit_status, e_termination), 0);
1196
    assertcp_eq!(offset_of!(__exit_status, e_exit), 2);
1197

1198
    // TODO: [2024/02/16] add faillog struct.
1199
    //       `faillog` is from older CentOS releases so low priority.
1200
    //       https://unix.stackexchange.com/a/182107/21203
1201

1202
    /// The [`utmpx` struct].
1203
    ///
1204
    /// The `utmp` struct is the exact same.
1205
    ///
1206
    /// Taken from [`/usr/include/x86_64-linux-gnu/bits/utmpx.h`] on Ubuntu 22.04
1207
    /// x86_64:
1208
    /// 
1209
    /// ```C
1210
    /// /* The structure describing an entry in the user accounting database.  */
1211
    /// struct utmpx
1212
    /// {
1213
    ///   short int ut_type;            /* Type of login.  */
1214
    ///   __pid_t ut_pid;               /* Process ID of login process.  */
1215
    ///   char ut_line[__UT_LINESIZE]
1216
    ///     __attribute_nonstring__;    /* Devicename.  */
1217
    ///   char ut_id[4]
1218
    ///     __attribute_nonstring__;    /* Inittab ID.  */
1219
    ///   char ut_user[__UT_NAMESIZE]
1220
    ///     __attribute_nonstring__;    /* Username.  */
1221
    ///   char ut_host[__UT_HOSTSIZE]
1222
    ///     __attribute_nonstring__;    /* Hostname for remote login.  */
1223
    ///   struct __exit_status ut_exit; /* Exit status of a process marked
1224
    ///                                    as DEAD_PROCESS.  */
1225
    /// /* The fields ut_session and ut_tv must be the same size when compiled
1226
    ///    32- and 64-bit.  This allows files and shared memory to be shared
1227
    ///    between 32- and 64-bit applications.  */
1228
    /// #if __WORDSIZE_TIME64_COMPAT32
1229
    ///   __int32_t ut_session;         /* Session ID, used for windowing.  */
1230
    ///   struct
1231
    ///   {
1232
    ///     __int32_t tv_sec;           /* Seconds.  */
1233
    ///     __int32_t tv_usec;          /* Microseconds.  */
1234
    ///   } ut_tv;                      /* Time entry was made.  */
1235
    /// #else
1236
    ///   long int ut_session;          /* Session ID, used for windowing.  */
1237
    ///   struct timeval ut_tv;         /* Time entry was made.  */
1238
    /// #endif
1239
    ///   __int32_t ut_addr_v6[4];      /* Internet address of remote host.  */
1240
    ///   char __glibc_reserved[20];    /* Reserved for future use.  */
1241
    /// };
1242
    /// ```
1243
    ///
1244
    /// The prior code snippet is reprinted here by allowance of the
1245
    /// GNU Lesser General Public License version 2.
1246
    ///
1247
    /// ---
1248
    ///
1249
    /// ```text
1250
    /// utmpx                   sizeof 384
1251
    /// utmpx.ut_type      @  0 sizeof   2
1252
    /// utmpx.ut_pid       @  4 sizeof   4
1253
    /// utmpx.ut_line      @  8 sizeof  32
1254
    /// utmpx.ut_id        @ 40 sizeof   4
1255
    /// utmpx.ut_user      @ 44 sizeof  32
1256
    /// utmpx.ut_name      @ 44 sizeof  32
1257
    /// utmpx.ut_host      @ 76 sizeof 256
1258
    /// utmpx.ut_exit      @332 sizeof   4
1259
    /// utmpx.ut_session   @336 sizeof   4
1260
    /// utmpx.ut_time      @340 sizeof   4
1261
    /// utmpx.ut_xtime     @340 sizeof   4
1262
    /// utmpx.ut_tv        @340 sizeof   8
1263
    /// utmpx.ut_tv.tv_sec @340 sizeof   4
1264
    /// utmpx.ut_tv.tv_usec@344 sizeof   4
1265
    /// utmpx.ut_addr      @348 sizeof   4
1266
    /// utmpx.ut_addr_v6   @348 sizeof  16
1267
    /// ```
1268
    ///
1269
    /// [`utmpx` struct]: https://linux.die.net/man/5/utmpx
1270
    /// [`/usr/include/x86_64-linux-gnu/bits/utmpx.h`]: https://elixir.bootlin.com/glibc/latest/source/sysdeps/gnu/bits/utmpx.h
1271
    #[derive(Clone, Copy)]
1272
    #[repr(C, align(4))]
1273
    #[allow(non_camel_case_types)]
1274
    pub struct utmpx {
1275
        pub ut_type: c_short,
1276
        pub ut_pid: pid_t,
1277
        pub ut_line: [c_char; UT_LINESIZE],
1278
        pub ut_id: [c_char; UT_IDSIZE],
1279
        pub ut_user: [c_char; UT_USERSIZE],
1280
        pub ut_host: [c_char; UT_HOSTSIZE],
1281
        pub ut_exit: __exit_status,
1282
        pub ut_session: i32,
1283
        pub ut_tv: __timeval,
1284
        pub ut_addr_v6: [i32; 4],
1285
        /* private fields */
1286
        pub __glibc_reserved: [i8; 20],
1287
    }
1288

1289
    pub const UTMPX_SZ: usize = size_of::<utmpx>();
1290
    pub const UTMPX_SZ_FO: FileOffset = UTMPX_SZ as FileOffset;
1291
    pub const UTMPX_TIMEVALUE_OFFSET: usize = offset_of!(utmpx, ut_tv);
1292
    pub const UTMPX_TIMEVALUE_SZ: usize = __TIMEVAL_SZ;
1293
    assertcp_eq!(UTMPX_SZ, 384);
1294
    assertcp_eq!(offset_of!(utmpx, ut_type), 0);
1295
    assertcp_eq!(offset_of!(utmpx, ut_pid), 4);
1296
    assertcp_eq!(offset_of!(utmpx, ut_line), 8);
1297
    assertcp_eq!(offset_of!(utmpx, ut_id), 40);
1298
    assertcp_eq!(offset_of!(utmpx, ut_user), 44);
1299
    assertcp_eq!(offset_of!(utmpx, ut_host), 76);
1300
    assertcp_eq!(offset_of!(utmpx, ut_exit), 332);
1301
    assertcp_eq!(offset_of!(utmpx, ut_session), 336);
1302
    assertcp_eq!(offset_of!(utmpx, ut_tv), 340);
1303
    assertcp_eq!(offset_of!(utmpx, ut_addr_v6), 348);
1304
    assertcp_eq!(offset_of!(utmpx, __glibc_reserved), 364);
1305

1306
    /// helpers for `fmt::Debug` trait
1307
    ///
1308
    /// The slicing in each `CStr` function below is to due to
1309
    /// `__attribute_nonstring__` which means the field may not end with a
1310
    /// null byte.
1311
    impl utmpx {
1312
        pub fn ut_line(&self) -> &CStr {
2,820✔
1313
            unsafe { CStr::from_ptr(self.ut_line[..UT_LINESIZE].as_ptr()) }
2,820✔
1314
        }
2,820✔
1315
        pub fn ut_id(&self) -> &CStr {
2,819✔
1316
            unsafe { CStr::from_ptr(self.ut_id[..UT_IDSIZE].as_ptr()) }
2,819✔
1317
        }
2,819✔
1318
        pub fn ut_user(&self) -> &CStr {
2,820✔
1319
            unsafe { CStr::from_ptr(self.ut_user[..UT_USERSIZE].as_ptr()) }
2,820✔
1320
        }
2,820✔
1321
        pub fn ut_host(&self) -> &CStr {
2,820✔
1322
            unsafe { CStr::from_ptr(self.ut_host[..UT_HOSTSIZE].as_ptr()) }
2,820✔
1323
        }
2,820✔
1324
    }
1325

1326
    /// From [`utmpx.h`], Linux 6.1
1327
    /// ```C
1328
    /// #define EMPTY           0
1329
    /// #define RUN_LVL         1
1330
    /// #define BOOT_TIME       2
1331
    /// #define NEW_TIME        3
1332
    /// #define OLD_TIME        4
1333
    /// #define INIT_PROCESS    5
1334
    /// #define LOGIN_PROCESS   6
1335
    /// #define USER_PROCESS    7
1336
    /// #define DEAD_PROCESS    8
1337
    /// ```
1338
    ///
1339
    /// [`utmpx.h`]: https://elixir.bootlin.com/musl/latest/source/include/utmpx.h
1340
    pub const UT_TYPES: [c_short; 9] = [
1341
        0, 1, 2, 3, 4, 5, 6, 7, 8
1342
    ];
1343
}
1344

1345
/// FixedStruct definitions found on NetBSD 9.3 i686 (x86_32).
1346
/// These are slightly different than amd64 (x86_64).
1347
#[allow(non_camel_case_types, unused)]
1348
pub mod netbsd_x8632 {
1349
    use crate::common::FileOffset;
1350
    use std::ffi::CStr;
1351
    use std::ffi::CString;
1352
    use std::mem::size_of;
1353
    use ::memoffset::offset_of;
1354
    use ::const_format::assertcp_eq;
1355

1356
    pub type comp_t = std::ffi::c_ushort;
1357
    pub type c_char = std::ffi::c_char;
1358
    pub type uid_t = std::ffi::c_uint;
1359
    pub type gid_t = std::ffi::c_uint;
1360
    pub type dev_t = std::ffi::c_longlong;
1361
    pub type pid_t = std::ffi::c_int;
1362
    pub type time_t = std::ffi::c_longlong;
1363
    pub type uint8_t = std::ffi::c_uchar;
1364
    pub type uint16_t = std::ffi::c_ushort;
1365

1366
    // acct
1367

1368
    pub const AFORK: u8 = 0x01;
1369
    pub const ASU: u8 = 0x02;
1370
    pub const ACOMPAT: u8 = 0x04;
1371
    pub const ACORE: u8 = 0x08;
1372
    pub const AXSIG: u8 = 0x10;
1373

1374
    pub const AC_FLAGS_MASK: u8 = AFORK | ASU | ACOMPAT | ACORE | AXSIG;
1375

1376
    pub const ACCT_COMM_SIZE: usize = 16;
1377

1378
    /// From [`/usr/include/sys/acct.h`] on NetBSD 9.3:
1379
    ///
1380
    /// ```C
1381
    /// /*
1382
    ///  * Accounting structures; these use a comp_t type which is a 3 bits base 8
1383
    ///  * exponent, 13 bit fraction ``floating point'' number.  Units are 1/AHZ
1384
    ///  * seconds.
1385
    ///  */
1386
    /// typedef uint16_t comp_t;
1387
    /// 
1388
    /// struct acct {
1389
    ///         char      ac_comm[16];  /* command name */
1390
    ///         comp_t    ac_utime;     /* user time */
1391
    ///         comp_t    ac_stime;     /* system time */
1392
    ///         comp_t    ac_etime;     /* elapsed time */
1393
    ///         time_t    ac_btime;     /* starting time */
1394
    ///         uid_t     ac_uid;       /* user id */
1395
    ///         gid_t     ac_gid;       /* group id */
1396
    ///         uint16_t  ac_mem;       /* average memory usage */
1397
    ///         comp_t    ac_io;        /* count of IO blocks */
1398
    ///         dev_t     ac_tty;       /* controlling tty */
1399
    /// 
1400
    /// #define AFORK   0x01            /* fork'd but not exec'd */
1401
    /// #define ASU     0x02            /* used super-user permissions */
1402
    /// #define ACOMPAT 0x04            /* used compatibility mode */
1403
    /// #define ACORE   0x08            /* dumped core */
1404
    /// #define AXSIG   0x10            /* killed by a signal */
1405
    ///         uint8_t   ac_flag;      /* accounting flags */
1406
    /// };
1407
    ///
1408
    /// /*
1409
    ///  * 1/AHZ is the granularity of the data encoded in the comp_t fields.
1410
    ///  * This is not necessarily equal to hz.
1411
    ///  */
1412
    /// #define AHZ     64
1413
    /// ```
1414
    ///
1415
    /// ---
1416
    ///
1417
    /// ```text
1418
    /// acct                 sizeof  56
1419
    /// acct.ac_comm    @  0 sizeof  16
1420
    /// acct.ac_utime   @ 16 sizeof   2
1421
    /// acct.ac_stime   @ 18 sizeof   2
1422
    /// acct.ac_etime   @ 20 sizeof   2
1423
    /// acct.ac_btime   @ 24 sizeof   8
1424
    /// acct.ac_uid     @ 32 sizeof   4
1425
    /// acct.ac_gid     @ 36 sizeof   4
1426
    /// acct.ac_mem     @ 40 sizeof   2
1427
    /// acct.ac_io      @ 42 sizeof   2
1428
    /// acct.ac_tty     @ 44 sizeof   8
1429
    /// acct.ac_flag    @ 52 sizeof   1
1430
    /// ```
1431
    ///
1432
    /// [`/usr/include/sys/acct.h`]: https://github.com/NetBSD/src/blob/1ba34bb0dc133c215a143601c18a24053c0e16e3/sys/sys/acct.h#L49
1433
    #[derive(Clone, Copy)]
1434
    #[repr(C, packed)]
1435
    #[allow(non_camel_case_types)]
1436
    pub struct acct {
1437
        pub ac_comm: [c_char; ACCT_COMM_SIZE],
1438
        pub ac_utime: comp_t,
1439
        pub ac_stime: comp_t,
1440
        pub ac_etime: comp_t,
1441
        pub __gap1: [u8; 2],
1442
        pub ac_btime: time_t,
1443
        pub ac_uid: uid_t,
1444
        pub ac_gid: gid_t,
1445
        pub ac_mem: uint16_t,
1446
        pub ac_io: comp_t,
1447
        pub ac_tty: dev_t,
1448
        pub ac_flag: uint8_t,
1449
        pub __gap3: [u8; 3],
1450
    }
1451

1452
    pub const ACCT_SZ: usize = size_of::<acct>();
1453
    pub const ACCT_SZ_FO: FileOffset = ACCT_SZ as FileOffset;
1454
    pub const ACCT_TIMEVALUE_OFFSET: usize = offset_of!(acct, ac_btime);
1455
    pub const ACCT_TIMEVALUE_SZ: usize = size_of::<time_t>();
1456
    assertcp_eq!(ACCT_SZ, 56);
1457
    assertcp_eq!(offset_of!(acct, ac_comm), 0);
1458
    assertcp_eq!(offset_of!(acct, ac_utime), 16);
1459
    assertcp_eq!(offset_of!(acct, ac_stime), 18);
1460
    assertcp_eq!(offset_of!(acct, ac_etime), 20);
1461
    assertcp_eq!(offset_of!(acct, ac_btime), 24);
1462
    assertcp_eq!(offset_of!(acct, ac_uid), 32);
1463
    assertcp_eq!(offset_of!(acct, ac_gid), 36);
1464
    assertcp_eq!(offset_of!(acct, ac_mem), 40);
1465
    assertcp_eq!(offset_of!(acct, ac_io), 42);
1466
    assertcp_eq!(offset_of!(acct, ac_tty), 44);
1467
    assertcp_eq!(offset_of!(acct, ac_flag), 52);
1468

1469
    impl acct {
1470
        pub fn ac_comm(&self) -> &CStr {
5✔
1471
            unsafe { CStr::from_ptr(self.ac_comm.as_ptr()) }
5✔
1472
        }
5✔
1473
    }
1474

1475
    // timeval
1476

1477
    /// ```text
1478
    /// timeval               sizeof  12
1479
    /// timeval.tv_sec   @  0 sizeof   8
1480
    /// timeval.tv_usec  @  8 sizeof   4
1481
    /// ```
1482
    #[derive(Clone, Copy)]
1483
    // BUG: align(4) has no effect, must use `packed`
1484
    //      see rust-lang/rust#48159 <https://github.com/rust-lang/rust/issues/48159>
1485
    #[repr(C, packed)]
1486
    #[allow(non_camel_case_types)]
1487
    pub struct timeval {
1488
        pub tv_sec: i64,
1489
        pub tv_usec: i32,
1490
    }
1491

1492
    pub const TIMEVAL_SZ: usize = size_of::<timeval>();
1493
    assertcp_eq!(TIMEVAL_SZ, 12);
1494
    assertcp_eq!(offset_of!(timeval, tv_sec), 0);
1495
    assertcp_eq!(offset_of!(timeval, tv_usec), 8);
1496

1497
    // lastlog
1498
    // same size as `linux_x86::lastlog`
1499

1500
    pub const UT_NAMESIZE: usize = 8;
1501
    pub const UT_LINESIZE: usize = 8;
1502
    pub const UT_HOSTSIZE: usize = 16;
1503

1504
    // lastlogx
1505

1506
    pub const UTX_LINESIZE: usize = 32;
1507
    pub const UTX_HOSTSIZE: usize = 256;
1508
    pub const UTX_SSSIZE: usize = 128;
1509

1510
    /// ```text
1511
    /// lastlogx               sizeof 428
1512
    /// lastlogx.ll_tv    @  0 sizeof  12
1513
    /// lastlogx.ll_line  @ 12 sizeof  32
1514
    /// lastlogx.ll_host  @ 44 sizeof 256
1515
    /// lastlogx.ll_ss    @300 sizeof 128
1516
    /// ```
1517
    ///
1518
    // TODO: [2024/03/10] This struct is 428 bytes whereas the scraped lastlogx
1519
    //       file is 65536 bytes (not divisible by 428).
1520
    //       see Issue #243 <https://github.com/jtmoon79/super-speedy-syslog-searcher/issues/243>
1521
    #[derive(Clone, Copy)]
1522
    #[repr(C, packed)]
1523
    #[allow(non_camel_case_types)]
1524
    pub struct lastlogx {
1525
        pub ll_tv: timeval,
1526
        pub ll_line: [c_char; UTX_LINESIZE],
1527
        pub ll_host: [c_char; UTX_HOSTSIZE],
1528
        pub ll_ss: [u8; UTX_SSSIZE],
1529
    }
1530

1531
    pub const LASTLOGX_SZ: usize = size_of::<lastlogx>();
1532
    pub const LASTLOGX_SZ_FO: FileOffset = LASTLOGX_SZ as FileOffset;
1533
    pub const LASTLOGX_TIMEVALUE_OFFSET: usize = offset_of!(lastlogx, ll_tv);
1534
    pub const LASTLOGX_TIMEVALUE_SZ: usize = TIMEVAL_SZ;
1535
    assertcp_eq!(LASTLOGX_SZ, 428);
1536
    assertcp_eq!(offset_of!(lastlogx, ll_tv), 0);
1537
    assertcp_eq!(offset_of!(lastlogx, ll_line), 12);
1538
    assertcp_eq!(offset_of!(lastlogx, ll_host), 44);
1539
    assertcp_eq!(offset_of!(lastlogx, ll_ss), 300);
1540

1541
    pub const PATH_LASTLOGX: &str = "/var/log/lastlogx";
1542

1543
    impl lastlogx {
1544
        pub fn ll_line(&self) -> &CStr {
5✔
1545
            unsafe { CStr::from_ptr(self.ll_line[..UTX_LINESIZE].as_ptr()) }
5✔
1546
        }
5✔
1547
        pub fn ll_host(&self) -> &CStr {
5✔
1548
            unsafe { CStr::from_ptr(self.ll_host[..UTX_HOSTSIZE].as_ptr()) }
5✔
1549
        }
5✔
1550
    }
1551

1552
    // utmpx
1553

1554
    pub const UTX_USERSIZE: usize = 32;
1555
    pub const UTX_IDSIZE: usize = 4;
1556

1557
    #[derive(Clone, Copy)]
1558
    #[repr(C, align(4))]
1559
    #[allow(non_camel_case_types)]
1560
    pub struct ut_exit {
1561
        pub e_termination: uint16_t,
1562
        pub e_exit: uint16_t,
1563
    }
1564

1565
    assertcp_eq!(offset_of!(ut_exit, e_termination), 0);
1566
    assertcp_eq!(offset_of!(ut_exit, e_exit), 2);
1567

1568
    /// ```text
1569
    /// utmpx                   sizeof 516
1570
    /// utmpx.ut_user      @  0 sizeof  32
1571
    /// utmpx.ut_name      @  0 sizeof  32
1572
    /// utmpx.ut_id        @ 32 sizeof   4
1573
    /// utmpx.ut_line      @ 36 sizeof  32
1574
    /// utmpx.ut_host      @ 68 sizeof 256
1575
    /// utmpx.ut_session   @324 sizeof   2
1576
    /// utmpx.ut_type      @326 sizeof   2
1577
    /// utmpx.ut_pid       @328 sizeof   4
1578
    /// utmpx.ut_exit      @332 sizeof   4
1579
    /// utmpx.ut_ss        @336 sizeof 128
1580
    /// utmpx.ut_xtime     @464 sizeof   8
1581
    /// utmpx.ut_tv        @464 sizeof  12
1582
    /// utmpx.ut_tv.tv_sec @464 sizeof   8
1583
    /// utmpx.ut_tv.tv_usec@472 sizeof   4
1584
    /// utmpx.ut_pad       @476 sizeof  40
1585
    /// ```
1586
    #[derive(Clone, Copy)]
1587
    #[repr(C, align(4))]
1588
    #[allow(non_camel_case_types)]
1589
    pub struct utmpx {
1590
        pub ut_name: [c_char; UTX_USERSIZE],
1591
        pub ut_id: [c_char; UTX_IDSIZE],
1592
        pub ut_line: [c_char; UTX_LINESIZE],
1593
        pub ut_host: [c_char; UTX_HOSTSIZE],
1594
        pub ut_session: uint16_t,
1595
        pub ut_type: uint16_t,
1596
        pub ut_pid: pid_t,
1597
        pub ut_exit: ut_exit,
1598
        pub ut_ss: [u8; UTX_SSSIZE],
1599
        pub ut_tv: timeval,
1600
        pub ut_pad: [c_char; 40],
1601
    }
1602

1603
    pub const UTMPX_SZ: usize = size_of::<utmpx>();
1604
    pub const UTMPX_SZ_FO: FileOffset = UTMPX_SZ as FileOffset;
1605
    pub const UTMPX_TIMEVALUE_OFFSET: usize = offset_of!(utmpx, ut_tv);
1606
    pub const UTMPX_TIMEVALUE_SZ: usize = TIMEVAL_SZ;
1607
    assertcp_eq!(UTMPX_SZ, 516);
1608
    assertcp_eq!(offset_of!(utmpx, ut_name), 0);
1609
    assertcp_eq!(offset_of!(utmpx, ut_id), 32);
1610
    assertcp_eq!(offset_of!(utmpx, ut_line), 36);
1611
    assertcp_eq!(offset_of!(utmpx, ut_host), 68);
1612
    assertcp_eq!(offset_of!(utmpx, ut_session), 324);
1613
    assertcp_eq!(offset_of!(utmpx, ut_type), 326);
1614
    assertcp_eq!(offset_of!(utmpx, ut_pid), 328);
1615
    assertcp_eq!(offset_of!(utmpx, ut_exit), 332);
1616
    assertcp_eq!(offset_of!(utmpx, ut_ss), 336);
1617
    assertcp_eq!(offset_of!(utmpx, ut_tv), 464);
1618
    assertcp_eq!(offset_of!(utmpx, ut_pad), 476);
1619

1620
    pub const PATH_UTMPX: &str = "/var/run/utmpx";
1621
    pub const PATH_WTMPX: &str = "/var/log/wtmpx";
1622

1623
    /// Helpers for use in `fmt::Debug` trait.
1624
    impl utmpx {
1625
        pub fn ut_name(&self) -> &CStr {
5✔
1626
            unsafe { CStr::from_ptr(self.ut_name[..UTX_USERSIZE].as_ptr()) }
5✔
1627
        }
5✔
1628
        pub fn ut_id(&self) -> &CStr {
5✔
1629
            unsafe { CStr::from_ptr(self.ut_id[..UTX_IDSIZE].as_ptr()) }
5✔
1630
        }
5✔
1631
        pub fn ut_line(&self) -> &CStr {
5✔
1632
            unsafe { CStr::from_ptr(self.ut_line[..UTX_LINESIZE].as_ptr()) }
5✔
1633
        }
5✔
1634
        pub fn ut_host(&self) -> &CStr {
5✔
1635
            unsafe { CStr::from_ptr(self.ut_host[..UTX_HOSTSIZE].as_ptr()) }
5✔
1636
        }
5✔
1637
    }
1638

1639
    /// From [`utmpx.h`] in NetBSD 9.3
1640
    /// ```C
1641
    /// #define EMPTY                0
1642
    /// #define RUN_LVL                1
1643
    /// #define BOOT_TIME        2
1644
    /// #define OLD_TIME        3
1645
    /// #define NEW_TIME        4
1646
    /// #define INIT_PROCESS        5
1647
    /// #define LOGIN_PROCESS        6
1648
    /// #define USER_PROCESS        7
1649
    /// #define DEAD_PROCESS        8
1650
    ///
1651
    /// #if defined(_NETBSD_SOURCE)
1652
    /// #define ACCOUNTING        9
1653
    /// #define SIGNATURE        10
1654
    /// #define DOWN_TIME        11
1655
    /// ```
1656
    ///
1657
    /// [`utmpx.h`]: https://github.com/NetBSD/src/blob/1ba34bb0dc133c215a143601c18a24053c0e16e3/include/utmpx.h
1658
    pub const UT_TYPES: [uint16_t; 12] = [
1659
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,11
1660
    ];
1661
}
1662

1663
/// FixedStruct definitions found on NetBSD 9.3 amd64 (x86_64).
1664
/// These are slightly different than i686 (x86_32).
1665
#[allow(non_camel_case_types, unused)]
1666
pub mod netbsd_x8664 {
1667
    use crate::common::FileOffset;
1668
    use std::ffi::CStr;
1669
    use std::mem::size_of;
1670
    use ::const_format::assertcp_eq;
1671
    use ::memoffset::offset_of;
1672

1673
    pub type c_char = std::ffi::c_char;
1674
    pub type pid_t = std::ffi::c_int;
1675
    pub type time_t = std::ffi::c_longlong;
1676
    pub type uint16_t = std::ffi::c_ushort;
1677

1678
    // timeval
1679

1680
    /// [from `time.h`]
1681
    /// ```C
1682
    /// struct timeval {
1683
    ///         time_t            tv_sec;                /* seconds */
1684
    ///         suseconds_t        tv_usec;        /* and microseconds */
1685
    /// };
1686
    /// ```
1687
    ///
1688
    /// ---
1689
    ///
1690
    /// ```text
1691
    /// timeval               sizeof  16
1692
    /// timeval.tv_sec   @  0 sizeof   8
1693
    /// timeval.tv_usec  @  8 sizeof   4
1694
    /// ```
1695
    ///
1696
    /// [from `time.h`]: https://github.com/NetBSD/src/blob/1ba34bb0dc133c215a143601c18a24053c0e16e3/sys/sys/time.h
1697
    #[derive(Clone, Copy)]
1698
    #[repr(C, align(4))]
1699
    #[allow(non_camel_case_types)]
1700
    pub struct timeval {
1701
        pub tv_sec: i64,
1702
        pub tv_usec: i32,
1703
        pub __pad: u32,
1704
    }
1705

1706
    pub const TIMEVAL_SZ: usize = size_of::<timeval>();
1707
    assertcp_eq!(TIMEVAL_SZ, 16);
1708
    assertcp_eq!(offset_of!(timeval, tv_sec), 0);
1709
    assertcp_eq!(offset_of!(timeval, tv_usec), 8);
1710
    assertcp_eq!(offset_of!(timeval, __pad), 12);
1711

1712
    // lastlog
1713

1714
    pub const UT_NAMESIZE: usize = 8;
1715
    pub const UT_LINESIZE: usize = 8;
1716
    pub const UT_HOSTSIZE: usize = 16;
1717

1718
    /// [from `utmp.h`]
1719
    /// ```C
1720
    /// #define        UT_NAMESIZE        8
1721
    /// #define        UT_LINESIZE        8
1722
    /// #define        UT_HOSTSIZE        16
1723
    ///
1724
    /// struct lastlog {
1725
    ///         time_t        ll_time;
1726
    ///         char        ll_line[UT_LINESIZE];
1727
    ///         char        ll_host[UT_HOSTSIZE];
1728
    /// };
1729
    /// ```
1730
    ///
1731
    /// ---
1732
    ///
1733
    /// ```text
1734
    /// lastlog               sizeof  32
1735
    /// lastlog.ll_time  @  0 sizeof   8
1736
    /// lastlog.ll_line  @  8 sizeof   8
1737
    /// lastlog.ll_host  @ 16 sizeof  16
1738
    /// ```
1739
    ///
1740
    /// Same struct and offsets were found on NetBSD 9.3 amd64 and i686.
1741
    ///
1742
    /// [from `utmp.h`]: https://github.com/NetBSD/src/blob/0d57c6f2979b7cf98608ef9ddbf6f739da0f8b42/include/utmp.h
1743
    #[derive(Clone, Copy)]
1744
    #[repr(C, align(8))]
1745
    #[allow(non_camel_case_types)]
1746
    pub struct lastlog {
1747
        pub ll_time: time_t,
1748
        pub ll_line: [c_char; UT_LINESIZE],
1749
        pub ll_host: [c_char; UT_HOSTSIZE],
1750
    }
1751

1752
    pub const LASTLOG_SZ: usize = size_of::<lastlog>();
1753
    pub const LASTLOG_SZ_FO: FileOffset = LASTLOG_SZ as FileOffset;
1754
    pub const LASTLOG_TIMEVALUE_OFFSET: usize = offset_of!(lastlog, ll_time);
1755
    pub const LASTLOG_TIMEVALUE_SZ: usize = size_of::<time_t>();
1756
    assertcp_eq!(LASTLOG_SZ, 32);
1757
    assertcp_eq!(offset_of!(lastlog, ll_time), 0);
1758
    assertcp_eq!(offset_of!(lastlog, ll_line), 8);
1759
    assertcp_eq!(offset_of!(lastlog, ll_host), 16);
1760

1761
    pub const PATH_LASTLOG: &str = "/var/log/lastlog";
1762

1763
    impl lastlog {
1764
        pub fn ll_line(&self) -> &CStr {
585✔
1765
            unsafe { CStr::from_ptr(self.ll_line[..UT_LINESIZE].as_ptr()) }
585✔
1766
        }
585✔
1767
        pub fn ll_host(&self) -> &CStr {
585✔
1768
            unsafe { CStr::from_ptr(self.ll_host[..UT_HOSTSIZE].as_ptr()) }
585✔
1769
        }
585✔
1770
    }
1771

1772
    // lastlogx
1773

1774
    pub const UTX_LINESIZE: usize = 32;
1775
    pub const UTX_HOSTSIZE: usize = 256;
1776
    pub const UTX_SSSIZE: usize = 128;
1777

1778
    /// [from `utmpx.h`]
1779
    /// ```C
1780
    /// #define _UTX_USERSIZE        32
1781
    /// #define _UTX_LINESIZE        32
1782
    /// #define        _UTX_IDSIZE        4
1783
    /// #define _UTX_HOSTSIZE        256
1784
    ///
1785
    /// #define ut_user ut_name
1786
    /// #define ut_xtime ut_tv.tv_sec
1787
    ///
1788
    /// #if defined(_NETBSD_SOURCE)
1789
    /// struct lastlogx {
1790
    ///         struct timeval ll_tv;                /* time entry was created */
1791
    ///         char ll_line[_UTX_LINESIZE];        /* tty name */
1792
    ///         char ll_host[_UTX_HOSTSIZE];        /* host name */
1793
    ///         struct sockaddr_storage ll_ss;        /* address where entry was made from */
1794
    /// };
1795
    /// #endif
1796
    /// ```
1797
    ///
1798
    /// ---
1799
    ///
1800
    /// ```text
1801
    /// lastlogx               sizeof 432
1802
    /// lastlogx.ll_tv    @  0 sizeof  16
1803
    /// lastlogx.ll_line  @ 16 sizeof  32
1804
    /// lastlogx.ll_host  @ 48 sizeof 256
1805
    /// lastlogx.ll_ss    @304 sizeof 128
1806
    /// ```
1807
    ///
1808
    /// Also see [`man lastlogx`].
1809
    ///
1810
    /// [from `utmpx.h`]: https://github.com/NetBSD/src/blob/0d57c6f2979b7cf98608ef9ddbf6f739da0f8b42/include/utmpx.h
1811
    /// [`man lastlogx`]: https://man.netbsd.org/lastlogx.5
1812
    // TODO: [2024/03/10] This struct is 432 bytes whereas lastlogx file is
1813
    //       65536 bytes (not divisble by 432).
1814
    //       see Issue #243 <https://github.com/jtmoon79/super-speedy-syslog-searcher/issues/243>
1815
    #[derive(Clone, Copy)]
1816
    #[repr(C, align(8))]
1817
    #[allow(non_camel_case_types)]
1818
    pub struct lastlogx {
1819
        pub ll_tv: timeval,
1820
        pub ll_line: [c_char; UTX_LINESIZE],
1821
        pub ll_host: [c_char; UTX_HOSTSIZE],
1822
        pub ll_ss: [u8; UTX_SSSIZE],
1823
    }
1824

1825
    pub const LASTLOGX_SZ: usize = size_of::<lastlogx>();
1826
    pub const LASTLOGX_SZ_FO: FileOffset = LASTLOG_SZ as FileOffset;
1827
    pub const LASTLOGX_TIMEVALUE_OFFSET: usize = offset_of!(lastlogx, ll_tv);
1828
    pub const LASTLOGX_TIMEVALUE_SZ: usize = TIMEVAL_SZ;
1829
    assertcp_eq!(LASTLOGX_SZ, 432);
1830
    assertcp_eq!(offset_of!(lastlogx, ll_tv), 0);
1831
    assertcp_eq!(offset_of!(lastlogx, ll_line), 16);
1832
    assertcp_eq!(offset_of!(lastlogx, ll_host), 48);
1833
    assertcp_eq!(offset_of!(lastlogx, ll_ss), 304);
1834

1835
    pub const PATH_LASTLOGX: &str = "/var/log/lastlogx";
1836

1837
    impl lastlogx {
1838
        pub fn ll_line(&self) -> &CStr {
2✔
1839
            unsafe { CStr::from_ptr(self.ll_line[..UTX_LINESIZE].as_ptr()) }
2✔
1840
        }
2✔
1841
        pub fn ll_host(&self) -> &CStr {
2✔
1842
            unsafe { CStr::from_ptr(self.ll_host[..UTX_HOSTSIZE].as_ptr()) }
2✔
1843
        }
2✔
1844
    }
1845

1846
    // utmp
1847

1848
    /// [from `utmp.h`]
1849
    /// ```C
1850
    /// #define        UT_NAMESIZE        8
1851
    /// #define        UT_LINESIZE        8
1852
    /// #define        UT_HOSTSIZE        16
1853
    ///
1854
    /// struct utmp {
1855
    ///         char        ut_line[UT_LINESIZE];
1856
    ///         char        ut_name[UT_NAMESIZE];
1857
    ///         char        ut_host[UT_HOSTSIZE];
1858
    ///         time_t        ut_time;
1859
    /// };
1860
    /// ```
1861
    ///
1862
    /// ---
1863
    ///
1864
    /// ```text
1865
    /// utmp                   sizeof  40
1866
    /// utmp.ut_line      @  0 sizeof   8
1867
    /// utmp.ut_name      @  8 sizeof   8
1868
    /// utmp.ut_host      @ 16 sizeof  16
1869
    /// utmp.ut_time      @ 32 sizeof   8
1870
    /// ```
1871
    ///
1872
    /// Same struct and offsets were found on NetBSD 9.3 amd64 and i686.
1873
    ///
1874
    /// [from `utmp.h`]: https://github.com/NetBSD/src/blob/0d57c6f2979b7cf98608ef9ddbf6f739da0f8b42/include/utmp.h
1875
    #[derive(Clone, Copy)]
1876
    #[repr(C, align(8))]
1877
    #[allow(non_camel_case_types)]
1878
    pub struct utmp {
1879
        pub ut_line: [c_char; UT_LINESIZE],
1880
        pub ut_name: [c_char; UT_NAMESIZE],
1881
        pub ut_host: [c_char; UT_HOSTSIZE],
1882
        pub ut_time: time_t,
1883
    }
1884

1885
    pub const UTMP_SZ: usize = size_of::<utmp>();
1886
    pub const UTMP_SZ_FO: FileOffset = UTMP_SZ as FileOffset;
1887
    pub const UTMP_TIMEVALUE_OFFSET: usize = offset_of!(utmp, ut_time);
1888
    pub const UTMP_TIMEVALUE_SZ: usize = size_of::<time_t>();
1889
    assertcp_eq!(UTMP_SZ, 40);
1890
    assertcp_eq!(offset_of!(utmp, ut_line), 0);
1891
    assertcp_eq!(offset_of!(utmp, ut_name), 8);
1892
    assertcp_eq!(offset_of!(utmp, ut_host), 16);
1893
    assertcp_eq!(offset_of!(utmp, ut_time), 32);
1894

1895
    pub const PATH_UTMP: &str = "/var/run/utmp";
1896
    pub const PATH_WTMP: &str = "/var/log/wtmp";
1897

1898
    impl utmp {
1899
        pub fn ut_line(&self) -> &CStr {
5✔
1900
            unsafe { CStr::from_ptr(self.ut_line[..UT_LINESIZE].as_ptr()) }
5✔
1901
        }
5✔
1902
        pub fn ut_name(&self) -> &CStr {
5✔
1903
            unsafe { CStr::from_ptr(self.ut_name[..UT_NAMESIZE].as_ptr()) }
5✔
1904
        }
5✔
1905
        pub fn ut_host(&self) -> &CStr {
5✔
1906
            unsafe { CStr::from_ptr(self.ut_host[..UT_HOSTSIZE].as_ptr()) }
5✔
1907
        }
5✔
1908
    }
1909

1910
    // utmpx
1911

1912
    pub const UTX_USERSIZE: usize = 32;
1913
    pub const UTX_IDSIZE: usize = 4;
1914

1915
    #[derive(Clone, Copy)]
1916
    #[repr(C, align(2))]
1917
    #[allow(non_camel_case_types)]
1918
    pub struct ut_exit {
1919
        pub e_termination: uint16_t,
1920
        pub e_exit: uint16_t,
1921
    }
1922

1923
    pub const UT_EXIT_SZ: usize = size_of::<ut_exit>();
1924
    assertcp_eq!(UT_EXIT_SZ, 4);
1925
    assertcp_eq!(offset_of!(ut_exit, e_termination), 0);
1926
    assertcp_eq!(offset_of!(ut_exit, e_exit), 2);
1927

1928
    /// [from `utmpx.h`]
1929
    /// ```C
1930
    /// #define _UTX_USERSIZE        32
1931
    /// #define _UTX_LINESIZE        32
1932
    /// #define        _UTX_IDSIZE        4
1933
    /// #define _UTX_HOSTSIZE        256
1934
    ///
1935
    /// #define ut_user ut_name
1936
    /// #define ut_xtime ut_tv.tv_sec
1937
    ///
1938
    /// struct utmpx {
1939
    ///         char ut_name[_UTX_USERSIZE];        /* login name */
1940
    ///         char ut_id[_UTX_IDSIZE];        /* inittab id */
1941
    ///         char ut_line[_UTX_LINESIZE];        /* tty name */
1942
    ///         char ut_host[_UTX_HOSTSIZE];        /* host name */
1943
    ///         uint16_t ut_session;                /* session id used for windowing */
1944
    ///         uint16_t ut_type;                /* type of this entry */
1945
    ///         pid_t ut_pid;                        /* process id creating the entry */
1946
    ///         struct {
1947
    ///                 uint16_t e_termination;        /* process termination signal */
1948
    ///                 uint16_t e_exit;        /* process exit status */
1949
    ///         } ut_exit;
1950
    ///         struct sockaddr_storage ut_ss;        /* address where entry was made from */
1951
    ///         struct timeval ut_tv;                /* time entry was created */
1952
    ///         uint8_t ut_pad[_UTX_PADSIZE];        /* reserved for future use */
1953
    /// };
1954
    /// ```
1955
    ///
1956
    /// ---
1957
    ///
1958
    /// ```text
1959
    /// EMPTY 0
1960
    /// RUN_LVL 1
1961
    /// BOOT_TIME 2
1962
    /// OLD_TIME 3
1963
    /// NEW_TIME 4
1964
    /// INIT_PROCESS 5
1965
    /// LOGIN_PROCESS 6
1966
    /// USER_PROCESS 7
1967
    /// DEAD_PROCESS 8
1968
    /// ACCOUNTING 9
1969
    /// SIGNATURE 10
1970
    /// DOWN_TIME 11
1971
    ///
1972
    /// UTX_USERSIZE 32
1973
    /// UTX_LINESIZE 32
1974
    /// UTX_IDSIZE 4
1975
    /// UTX_HOSTSIZE 256
1976
    ///
1977
    /// utmpx                   sizeof 520
1978
    /// utmpx.ut_user      @  0 sizeof  32
1979
    /// utmpx.ut_name      @  0 sizeof  32
1980
    /// utmpx.ut_id        @ 32 sizeof   4
1981
    /// utmpx.ut_line      @ 36 sizeof  32
1982
    /// utmpx.ut_host      @ 68 sizeof 256
1983
    /// utmpx.ut_session   @324 sizeof   2
1984
    /// utmpx.ut_type      @326 sizeof   2
1985
    /// utmpx.ut_pid       @328 sizeof   4
1986
    /// utmpx.ut_exit      @332 sizeof   4
1987
    /// utmpx.ut_xtime     @464 sizeof   8
1988
    /// utmpx.ut_tv        @464 sizeof  16
1989
    /// utmpx.ut_tv.tv_sec @464 sizeof   8
1990
    /// utmpx.ut_tv.tv_usec@472 sizeof   4
1991
    /// utmpx.ut_pad       @480 sizeof  36
1992
    /// ```
1993
    ///
1994
    /// [from `utmpx.h`]: https://github.com/NetBSD/src/blob/0d57c6f2979b7cf98608ef9ddbf6f739da0f8b42/include/utmpx.h
1995
    #[derive(Clone, Copy)]
1996
    #[repr(C, align(8))]
1997
    #[allow(non_camel_case_types)]
1998
    pub struct utmpx {
1999
        pub ut_user: [c_char; UTX_USERSIZE],
2000
        pub ut_id: [c_char; UTX_IDSIZE],
2001
        pub ut_line: [c_char; UTX_LINESIZE],
2002
        pub ut_host: [c_char; UTX_HOSTSIZE],
2003
        pub ut_session: uint16_t,
2004
        pub ut_type: uint16_t,
2005
        pub ut_pid: pid_t,
2006
        pub ut_exit: ut_exit,
2007
        pub __gap1: [c_char; 128],
2008
        pub ut_tv: timeval,
2009
        pub ut_pad: [c_char; 36],
2010
    }
2011

2012
    pub const UTMPX_SZ: usize = size_of::<utmpx>();
2013
    pub const UTMPX_SZ_FO: FileOffset = UTMPX_SZ as FileOffset;
2014
    pub const UTMPX_TIMEVALUE_OFFSET: usize = offset_of!(utmpx, ut_tv);
2015
    pub const UTMPX_TIMEVALUE_SZ: usize = TIMEVAL_SZ;
2016
    assertcp_eq!(UTMPX_SZ, 520);
2017
    assertcp_eq!(offset_of!(utmpx, ut_user), 0);
2018
    assertcp_eq!(offset_of!(utmpx, ut_id), 32);
2019
    assertcp_eq!(offset_of!(utmpx, ut_line), 36);
2020
    assertcp_eq!(offset_of!(utmpx, ut_host), 68);
2021
    assertcp_eq!(offset_of!(utmpx, ut_session), 324);
2022
    assertcp_eq!(offset_of!(utmpx, ut_type), 326);
2023
    assertcp_eq!(offset_of!(utmpx, ut_pid), 328);
2024
    assertcp_eq!(offset_of!(utmpx, ut_exit), 332);
2025
    assertcp_eq!(offset_of!(utmpx, ut_tv), 464);
2026
    assertcp_eq!(offset_of!(utmpx, ut_pad), 480);
2027

2028
    pub const PATH_UTMPX: &str = "/var/run/utmpx";
2029
    pub const PATH_WTMPX: &str = "/var/log/wtmpx";
2030

2031
    /// Helpers for use in `fmt::Debug` trait.
2032
    impl utmpx {
2033
        pub fn ut_user(&self) -> &CStr {
5✔
2034
            unsafe { CStr::from_ptr(self.ut_user[..UTX_USERSIZE].as_ptr()) }
5✔
2035
        }
5✔
2036
        pub fn ut_id(&self) -> &CStr {
5✔
2037
            unsafe { CStr::from_ptr(self.ut_id[..UTX_IDSIZE].as_ptr()) }
5✔
2038
        }
5✔
2039
        pub fn ut_line(&self) -> &CStr {
5✔
2040
            unsafe { CStr::from_ptr(self.ut_line[..UTX_LINESIZE].as_ptr()) }
5✔
2041
        }
5✔
2042
        pub fn ut_host(&self) -> &CStr {
5✔
2043
            unsafe { CStr::from_ptr(self.ut_host[..UTX_HOSTSIZE].as_ptr()) }
5✔
2044
        }
5✔
2045
    }
2046

2047
    /// From [`utmpx.h`] in NetBSD 9.3
2048
    /// ```C
2049
    /// #define EMPTY                0
2050
    /// #define RUN_LVL                1
2051
    /// #define BOOT_TIME        2
2052
    /// #define OLD_TIME        3
2053
    /// #define NEW_TIME        4
2054
    /// #define INIT_PROCESS        5
2055
    /// #define LOGIN_PROCESS        6
2056
    /// #define USER_PROCESS        7
2057
    /// #define DEAD_PROCESS        8
2058
    ///
2059
    /// #if defined(_NETBSD_SOURCE)
2060
    /// #define ACCOUNTING        9
2061
    /// #define SIGNATURE        10
2062
    /// #define DOWN_TIME        11
2063
    /// ```
2064
    ///
2065
    /// [`utmpx.h`]: https://github.com/NetBSD/src/blob/1ba34bb0dc133c215a143601c18a24053c0e16e3/include/utmpx.h
2066
    pub const UT_TYPES: [uint16_t; 12] = [
2067
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,11
2068
    ];
2069
}
2070

2071
/// FixedStruct definitions found on OpenBSD 7.2 i386 (x86_32) and amd64
2072
/// (x86_64).
2073
///
2074
/// The same sizes were found for OpenBSD on i386 and amd64; see repository file
2075
/// `logs/OpenBSD7.4/x86_64/utmp-offsets_amd64_OpenBSD_7.4_.out`.
2076
///
2077
/// See [the 7.2 OpenBSD code base].
2078
/// See [`man utmp`].
2079
/// See [`utmp.h` from the OpenBSD 7.2 release].
2080
///
2081
/// [the 7.2 OpenBSD code base]: https://github.com/openbsd/src/blob/20248fc4cbb7c0efca41a8aafd40db7747023515/include/utmp.h
2082
/// [`man utmp`]: https://web.archive.org/web/20230607124838/https://man.openbsd.org/utmp.5
2083
/// [`utmp.h` from the OpenBSD 7.2 release]: https://github.com/openbsd/src/blob/20248fc4cbb7c0efca41a8aafd40db7747023515/include/utmp.h#L56-L67
2084
#[allow(non_camel_case_types, unused)]
2085
pub mod openbsd_x86 {
2086
    use crate::common::FileOffset;
2087
    use std::ffi::CStr;
2088
    use std::mem::size_of;
2089
    use ::const_format::assertcp_eq;
2090
    use ::memoffset::offset_of;
2091

2092
    pub type c_char = std::ffi::c_char;
2093
    pub type time_t = std::ffi::c_longlong;
2094

2095
    pub const UT_NAMESIZE: usize = 32;
2096
    pub const UT_LINESIZE: usize = 8;
2097
    pub const UT_HOSTSIZE: usize = 256;
2098

2099
    // lastlog
2100

2101
    /// From <https://github.com/openbsd/src/blob/20248fc4cbb7c0efca41a8aafd40db7747023515/include/utmp.h#L56C1-L61C1>
2102
    ///
2103
    /// ```C
2104
    /// #define        UT_NAMESIZE        32
2105
    /// #define        UT_LINESIZE        8
2106
    /// #define        UT_HOSTSIZE        256
2107
    ///
2108
    /// struct lastlog {
2109
    ///         time_t        ll_time;
2110
    ///         char        ll_line[UT_LINESIZE];
2111
    ///         char        ll_host[UT_HOSTSIZE];
2112
    /// };
2113
    /// ```
2114
    ///
2115
    /// ---
2116
    ///
2117
    /// ```text
2118
    /// lastlog               sizeof 272
2119
    /// lastlog.ll_time  @  0 sizeof   8
2120
    /// lastlog.ll_line  @  8 sizeof   8
2121
    /// lastlog.ll_host  @ 16 sizeof 256
2122
    /// ```
2123
    #[derive(Clone, Copy)]
2124
    #[repr(C, align(8))]
2125
    #[allow(non_camel_case_types)]
2126
    pub struct lastlog {
2127
        pub ll_time: time_t,
2128
        pub ll_line: [c_char; UT_LINESIZE],
2129
        pub ll_host: [c_char; UT_HOSTSIZE],
2130
    }
2131

2132
    pub const LASTLOG_SZ: usize = size_of::<lastlog>();
2133
    pub const LASTLOG_SZ_FO: FileOffset = LASTLOG_SZ as FileOffset;
2134
    pub const LASTLOG_TIMEVALUE_OFFSET: usize = offset_of!(lastlog, ll_time);
2135
    pub const LASTLOG_TIMEVALUE_SZ: usize = size_of::<time_t>();
2136
    assertcp_eq!(LASTLOG_SZ, 272);
2137
    assertcp_eq!(offset_of!(lastlog, ll_time), 0);
2138
    assertcp_eq!(offset_of!(lastlog, ll_line), 8);
2139
    assertcp_eq!(offset_of!(lastlog, ll_host), 16);
2140

2141
    pub const PATH_LASTLOG: &str = "/var/log/lastlog";
2142

2143
    /// Helpers for use in `fmt::Debug` trait.
2144
    ///
2145
    /// The slicing in each `CStr` function below is to due to:
2146
    /// ```C
2147
    /// /*
2148
    ///  * Note that these are *not* C strings and thus are not
2149
    ///  * guaranteed to be NUL-terminated.
2150
    /// */
2151
    /// ```
2152
    /// <https://github.com/openbsd/src/blob/20248fc4cbb7c0efca41a8aafd40db7747023515/include/utmp.h#L51-L54>
2153
    ///
2154
    /// to avoid the `CStr` constructor from reading past the end of the given
2155
    /// field into the next field.
2156
    impl lastlog {
2157
        pub fn ll_line(&self) -> &CStr {
5✔
2158
            unsafe { CStr::from_ptr(self.ll_line[..UT_LINESIZE].as_ptr()) }
5✔
2159
        }
5✔
2160
        pub fn ll_host(&self) -> &CStr {
5✔
2161
            unsafe { CStr::from_ptr(self.ll_host[..UT_HOSTSIZE].as_ptr()) }
5✔
2162
        }
5✔
2163
    }
2164

2165
    // utmp
2166

2167
    /// From <https://github.com/openbsd/src/blob/20248fc4cbb7c0efca41a8aafd40db7747023515/include/utmp.h#L62-L67>
2168
    ///
2169
    /// ```C
2170
    /// #define        UT_NAMESIZE        32
2171
    /// #define        UT_LINESIZE        8
2172
    /// #define        UT_HOSTSIZE        256
2173
    ///
2174
    /// struct utmp {
2175
    ///         char        ut_line[UT_LINESIZE];
2176
    ///         char        ut_name[UT_NAMESIZE];
2177
    ///         char        ut_host[UT_HOSTSIZE];
2178
    ///         time_t        ut_time;
2179
    /// };
2180
    /// ```
2181
    ///
2182
    /// ---
2183
    ///
2184
    /// ```text
2185
    /// utmp                   sizeof 304
2186
    /// utmp.ut_line      @  0 sizeof   8
2187
    /// utmp.ut_name      @  8 sizeof  32
2188
    /// utmp.ut_host      @ 40 sizeof 256
2189
    /// utmp.ut_time      @296 sizeof   8
2190
    /// ```
2191
    #[derive(Clone, Copy)]
2192
    #[repr(C, align(8))]
2193
    #[allow(non_camel_case_types)]
2194
    pub struct utmp {
2195
        pub ut_line: [c_char; UT_LINESIZE],
2196
        pub ut_name: [c_char; UT_NAMESIZE],
2197
        pub ut_host: [c_char; UT_HOSTSIZE],
2198
        pub ut_time: time_t,
2199
    }
2200

2201
    pub const UTMP_SZ: usize = size_of::<utmp>();
2202
    pub const UTMP_SZ_FO: FileOffset = UTMP_SZ as FileOffset;
2203
    pub const UTMP_TIMEVALUE_OFFSET: usize = offset_of!(utmp, ut_time);
2204
    pub const UTMP_TIMEVALUE_SZ: usize = size_of::<time_t>();
2205
    assertcp_eq!(UTMP_SZ, 304);
2206
    assertcp_eq!(offset_of!(utmp, ut_line), 0);
2207
    assertcp_eq!(offset_of!(utmp, ut_name), 8);
2208
    assertcp_eq!(offset_of!(utmp, ut_host), 40);
2209
    assertcp_eq!(offset_of!(utmp, ut_time), 296);
2210

2211
    pub const PATH_UTMP: &str = "/var/run/utmp";
2212
    pub const PATH_WTMP: &str = "/var/log/wtmp";
2213

2214
    /// Helpers for use in `fmt::Debug` trait.
2215
    ///
2216
    /// The slicing in each `CStr` function below is to due to:
2217
    /// ```C
2218
    /// /*
2219
    ///  * Note that these are *not* C strings and thus are not
2220
    ///  * guaranteed to be NUL-terminated.
2221
    /// */
2222
    /// ```
2223
    /// <https://github.com/openbsd/src/blob/20248fc4cbb7c0efca41a8aafd40db7747023515/include/utmp.h#L51-L54>
2224
    ///
2225
    /// to avoid the `CStr` constructor from reading past the end of the given
2226
    /// field into the next field.
2227
    impl utmp {
2228
        pub fn ut_line(&self) -> &CStr {
5✔
2229
            unsafe { CStr::from_ptr(self.ut_line[..UT_LINESIZE].as_ptr()) }
5✔
2230
        }
5✔
2231
        pub fn ut_name(&self) -> &CStr {
5✔
2232
            unsafe { CStr::from_ptr(self.ut_name[..UT_NAMESIZE].as_ptr()) }
5✔
2233
        }
5✔
2234
        pub fn ut_host(&self) -> &CStr {
5✔
2235
            unsafe { CStr::from_ptr(self.ut_host[..UT_HOSTSIZE].as_ptr()) }
5✔
2236
        }
5✔
2237
    }
2238
}
2239

2240
/// Maximum size among all `acct`/`lastlog`/`utmp`/etc. C structs
2241
pub const ENTRY_SZ_MAX: usize = max16(
2242
    freebsd_x8664::UTMPX_SZ,
2243
    linux_arm64aarch64::LASTLOG_SZ,
2244
    linux_arm64aarch64::UTMPX_SZ,
2245
    linux_x86::ACCT_SZ,
2246
    linux_x86::ACCT_V3_SZ,
2247
    linux_x86::LASTLOG_SZ,
2248
    linux_x86::UTMPX_SZ,
2249
    netbsd_x8632::ACCT_SZ,
2250
    netbsd_x8632::LASTLOGX_SZ,
2251
    netbsd_x8632::UTMPX_SZ,
2252
    netbsd_x8664::LASTLOG_SZ,
2253
    netbsd_x8664::LASTLOGX_SZ,
2254
    netbsd_x8664::UTMP_SZ,
2255
    netbsd_x8664::UTMPX_SZ,
2256
    openbsd_x86::LASTLOG_SZ,
2257
    openbsd_x86::UTMP_SZ,
2258
);
2259

2260
/// Minimum size among all `acct`/`lastlog`/`utmp`/etc. C structs
2261
pub const ENTRY_SZ_MIN: usize = min16(
2262
    freebsd_x8664::UTMPX_SZ,
2263
    linux_arm64aarch64::LASTLOG_SZ,
2264
    linux_arm64aarch64::UTMPX_SZ,
2265
    linux_x86::ACCT_SZ,
2266
    linux_x86::ACCT_V3_SZ,
2267
    linux_x86::LASTLOG_SZ,
2268
    linux_x86::UTMPX_SZ,
2269
    netbsd_x8632::ACCT_SZ,
2270
    netbsd_x8632::LASTLOGX_SZ,
2271
    netbsd_x8632::UTMPX_SZ,
2272
    netbsd_x8664::LASTLOG_SZ,
2273
    netbsd_x8664::LASTLOGX_SZ,
2274
    netbsd_x8664::UTMP_SZ,
2275
    netbsd_x8664::UTMPX_SZ,
2276
    openbsd_x86::LASTLOG_SZ,
2277
    openbsd_x86::UTMP_SZ,
2278
);
2279

2280
/// Maximum size among all time values for all C structs
2281
pub const TIMEVAL_SZ_MAX: usize = max16(
2282
    freebsd_x8664::TIMEVAL_SZ,
2283
    linux_arm64aarch64::LASTLOG_TIMEVALUE_SZ,
2284
    linux_arm64aarch64::UTMPX_TIMEVALUE_SZ,
2285
    linux_x86::ACCT_TIMEVALUE_SZ,
2286
    linux_x86::ACCT_V3_TIMEVALUE_SZ,
2287
    linux_x86::LASTLOG_TIMEVALUE_SZ,
2288
    linux_x86::UTMPX_TIMEVALUE_SZ,
2289
    netbsd_x8632::ACCT_TIMEVALUE_SZ,
2290
    netbsd_x8632::LASTLOGX_TIMEVALUE_SZ,
2291
    netbsd_x8632::UTMPX_TIMEVALUE_SZ,
2292
    netbsd_x8664::LASTLOG_TIMEVALUE_SZ,
2293
    netbsd_x8664::LASTLOGX_TIMEVALUE_SZ,
2294
    netbsd_x8664::UTMP_TIMEVALUE_SZ,
2295
    netbsd_x8664::UTMPX_TIMEVALUE_SZ,
2296
    openbsd_x86::LASTLOG_TIMEVALUE_SZ,
2297
    openbsd_x86::UTMP_TIMEVALUE_SZ,
2298
);
2299

2300
/// Map [`utmp.ut_type`] value, implied in the index offset, to it's `str`
2301
/// representation. These values and definitions appear consistent across all
2302
/// platforms, except NetBSD appends three values.
2303
///
2304
/// See [NetBSD 9.3 `utmpx.h`].
2305
///
2306
/// [`utmp.ut_type`]: https://www.man7.org/linux/man-pages/man5/utmp.5.html
2307
/// [NetBSD 9.3 `utmpx.h`]: https://github.com/NetBSD/src/blob/0d57c6f2979b7cf98608ef9ddbf6f739da0f8b42/include/utmpx.h
2308
pub const UT_TYPE_VAL_TO_STR: &[&str] = &[
2309
    "EMPTY", // 0
2310
    "RUN_LVL", // 1
2311
    "BOOT_TIME", // 2
2312
    "NEW_TIME", // 3
2313
    "OLD_TIME", // 4
2314
    "INIT_PROCESS", // 5
2315
    "LOGIN_PROCESS", // 6
2316
    "USER_PROCESS", // 7
2317
    "DEAD_PROCESS", // 8
2318
    // NetBSD adds these values
2319
    "ACCOUNTING", // 9
2320
    "SIGNATURE", // 10
2321
    "DOWN_TIME", // 11
2322
];
2323
/// Count of entries in [`UT_TYPE_VAL_TO_STR`].
2324
pub const UT_TYPE_VAL_TO_STR_LEN: usize = UT_TYPE_VAL_TO_STR.len();
2325
#[allow(non_upper_case_globals)]
2326
pub const UT_TYPE_VAL_TO_STR_LEN_i16: i16 = UT_TYPE_VAL_TO_STR.len() as i16;
2327
#[allow(non_upper_case_globals)]
2328
pub const UT_TYPE_VAL_TO_STR_LEN_u16: u16 = UT_TYPE_VAL_TO_STR.len() as u16;
2329

2330
/// common denominator **t**ime **v**alue type representing
2331
/// seconds since Unix epoch
2332
#[allow(non_camel_case_types)]
2333
pub type tv_sec_type = i64;
2334

2335
/// common denominator **t**ime **v**alue type representing additional
2336
/// sub-second microseconds since Unix epoch
2337
#[allow(non_camel_case_types)]
2338
pub type tv_usec_type = i64;
2339

2340
/// common nanoseconds type used as intermediate representation during
2341
/// conversion to [`DateTimeL`]
2342
///
2343
/// [`DateTimeL`]: crate::data::datetime::DateTimeL
2344
#[allow(non_camel_case_types)]
2345
pub type nsecs_type = u32;
2346

2347
#[allow(non_camel_case_types)]
2348
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
2349
/// **t**ime **v**alue pair type
2350
pub struct tv_pair_type(pub tv_sec_type, pub tv_usec_type);
2351

2352
impl std::fmt::Debug for tv_pair_type {
2353
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221,887✔
2354
        write!(f, "{}.{}", self.0, self.1)
221,887✔
2355
    }
221,887✔
2356
}
2357

2358
/// `Box` pointer to a `dyn`amically dispatched _Trait object_
2359
/// [`FixedStructTrait`].
2360
pub type FixedStructDynPtr = Box<dyn FixedStructTrait>;
2361

2362
/// An abstraction for representing varying fixed-size C structs.
2363
/// This includes record-keeping structs _acct_, _lastlog_, _utmp_ defined
2364
/// in the namespaces [`freebsd_x8664`], [`linux_arm64aarch64`], etc.
2365
/// Each specific definition defined in those namespaces must `impl`ement this
2366
/// trait.
2367
///
2368
/// Because this uses `dyn` trait then it must be an "Object safe trait".
2369
/// Being "Object safe trait" enforces limitations on behavior, e.g. cannot
2370
/// require trait `Sized` which implies cannot require trait `Clone`, among
2371
/// other limitations.
2372
///
2373
/// References to specific implementations of this Trait are stored as a Box
2374
/// pointer to the trait object, `Box<dyn FixedStructTrait>`, which is aliased
2375
/// as [`FixedStructDynPtr`]. This allows dynamic dispatching of the at runtime.
2376
///
2377
/// `Send` required for sending from file processing thread to main thread
2378
///
2379
/// `std::marker::Sync` required for `lazy_static!`
2380
///
2381
/// See <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
2382
pub trait FixedStructTrait
2383
where Self: Send,
2384
      Self: std::marker::Sync,
2385
{
2386
    /// the type of the struct
2387
    fn fixedstruct_type(&self) -> FixedStructType;
2388
    /// the size of the struct in bytes
2389
    fn size(&self) -> usize;
2390

2391
    // TODO: [2024/01/28] is there a more rustic way to combine these into one
2392
    //       `as_fixedstruct_type` that is just real smart? so I don't have to repeat
2393
    //       the same function names in each `impl` block, i.e. each impl block
2394
    //       only explicitly defines a few of the functions, the rest panic.
2395
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx;
2396
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog;
2397
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx;
2398
    fn as_linux_x86_acct(&self) -> &linux_x86::acct;
2399
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3;
2400
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog;
2401
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx;
2402
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct;
2403
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx;
2404
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx;
2405
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog;
2406
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx;
2407
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp;
2408
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx;
2409
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog;
2410
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp;
2411
}
2412

2413
impl fmt::Debug for dyn FixedStructTrait {
2414
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2,280✔
2415
        match self.fixedstruct_type() {
2,280✔
2416
            FixedStructType::Fs_Freebsd_x8664_Utmpx => {
2417
                self.as_freebsd_x8664_utmpx().fmt(f)
1✔
2418
            }
2419
            FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => {
2420
                self.as_linux_arm64aarch64_lastlog().fmt(f)
1✔
2421
            }
2422
            FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => {
2423
                self.as_linux_arm64aarch64_utmpx().fmt(f)
1✔
2424
            }
2425
            FixedStructType::Fs_Linux_x86_Acct => {
2426
                self.as_linux_x86_acct().fmt(f)
1✔
2427
            }
2428
            FixedStructType::Fs_Linux_x86_Acct_v3 => {
2429
                self.as_linux_x86_acct_v3().fmt(f)
1✔
2430
            }
2431
            FixedStructType::Fs_Linux_x86_Lastlog => {
2432
                self.as_linux_x86_lastlog().fmt(f)
15✔
2433
            }
2434
            FixedStructType::Fs_Linux_x86_Utmpx => {
2435
                self.as_linux_x86_utmpx().fmt(f)
2,252✔
2436
            }
2437
            FixedStructType::Fs_Netbsd_x8632_Acct => {
2438
                self.as_netbsd_x8632_acct().fmt(f)
1✔
2439
            }
2440
            FixedStructType::Fs_Netbsd_x8632_Lastlogx => {
2441
                self.as_netbsd_x8632_lastlogx().fmt(f)
1✔
2442
            }
2443
            FixedStructType::Fs_Netbsd_x8632_Utmpx => {
2444
                self.as_netbsd_x8632_utmpx().fmt(f)
1✔
2445
            }
2446
            FixedStructType::Fs_Netbsd_x8664_Lastlog => {
2447
                self.as_netbsd_x8664_lastlog().fmt(f)
1✔
2448
            }
2449
            FixedStructType::Fs_Netbsd_x8664_Lastlogx => {
2450
                self.as_netbsd_x8664_lastlogx().fmt(f)
×
2451
            }
2452
            FixedStructType::Fs_Netbsd_x8664_Utmp => {
2453
                self.as_netbsd_x8664_utmp().fmt(f)
1✔
2454
            }
2455
            FixedStructType::Fs_Netbsd_x8664_Utmpx => {
2456
                self.as_netbsd_x8664_utmpx().fmt(f)
1✔
2457
            }
2458
            FixedStructType::Fs_Openbsd_x86_Lastlog => {
2459
                self.as_openbsd_x86_lastlog().fmt(f)
1✔
2460
            }
2461
            FixedStructType::Fs_Openbsd_x86_Utmp => {
2462
                self.as_openbsd_x86_utmp().fmt(f)
1✔
2463
            }
2464
        }
2465
    }
2,280✔
2466
}
2467

2468
// freebsd_x8664::utmpx
2469

2470
impl FixedStructTrait for freebsd_x8664::utmpx {
2471
    fn fixedstruct_type(&self) -> FixedStructType {
13✔
2472
        FixedStructType::Fs_Freebsd_x8664_Utmpx
13✔
2473
    }
13✔
2474
    fn size(&self) -> usize {
9✔
2475
        freebsd_x8664::UTMPX_SZ
9✔
2476
    }
9✔
2477

2478
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
11✔
2479
        self
11✔
2480
    }
11✔
2481
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
2482
        panic!("as_linux_arm64aarch64_lastlog() called on freebsd_x8664::utmpx");
×
2483
    }
2484
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
2485
        panic!("as_linux_arm64aarch64_utmpx() called on freebsd_x8664::utmpx");
×
2486
    }
2487
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
2488
        panic!("as_linux_x86_acct() called on freebsd_x8664::utmpx");
×
2489
    }
2490
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
2491
        panic!("as_linux_x86_acct_v3() called on freebsd_x8664::utmpx");
×
2492
    }
2493
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
2494
        panic!("as_linux_x86_lastlog() called on freebsd_x8664::utmpx");
×
2495
    }
2496
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
2497
        panic!("as_linux_x86_utmpx() called on freebsd_x8664::utmpx");
×
2498
    }
2499
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
2500
        panic!("as_netbsd_x8632_acct() called on freebsd_x8664::utmpx");
×
2501
    }
2502
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
2503
        panic!("as_netbsd_x8632_lastlogx() called on freebsd_x8664::utmpx");
×
2504
    }
2505
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
2506
        panic!("as_netbsd_x8632_utmpx() called on freebsd_x8664::utmpx");
×
2507
    }
2508
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
2509
        panic!("as_netbsd_x8664_lastlog() called on freebsd_x8664::utmpx");
×
2510
    }
2511
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
2512
        panic!("as_netbsd_x8664_lastlogx() called on freebsd_x8664::utmpx");
×
2513
    }
2514
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
2515
        panic!("as_netbsd_x8664_utmp() called on freebsd_x8664::utmpx");
×
2516
    }
2517
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
2518
        panic!("as_netbsd_x8664_utmpx() called on freebsd_x8664::utmpx");
×
2519
    }
2520
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
2521
        panic!("as_openbsd_x86_lastlog() called on freebsd_x8664::utmpx");
×
2522
    }
2523
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
2524
        panic!("as_openbsd_x86_utmp() called on freebsd_x8664::utmpx");
×
2525
    }
2526
}
2527

2528
impl fmt::Debug for freebsd_x8664::utmpx {
2529
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
2530
        let ut_pid_s = match self.ut_type {
2✔
2531
            x if (0..UT_TYPE_VAL_TO_STR_LEN_i16).contains(&x) =>
2✔
2532
                format!("{} ({})", self.ut_type, UT_TYPE_VAL_TO_STR[self.ut_type as usize]),
2✔
2533
            _ => format!("{} (UNKNOWN)", self.ut_type),
×
2534
        };
2535
        f.debug_struct("freebsd_x8664::utmpx")
2✔
2536
            .field("size", &self.size())
2✔
2537
            .field("ut_type", &self.ut_type)
2✔
2538
            .field("ut_pid", &format_args!("{}", ut_pid_s))
2✔
2539
            .field("ut_line", &self.ut_line())
2✔
2540
            .field("ut_id", &self.ut_id())
2✔
2541
            .field("ut_user", &self.ut_user())
2✔
2542
            .field("ut_host", &self.ut_host())
2✔
2543
            .field("ut_tv.tv_sec", &self.ut_tv.tv_sec)
2✔
2544
            .field("ut_tv.tv_usec", &self.ut_tv.tv_usec)
2✔
2545
            .finish()
2✔
2546
    }
2✔
2547
}
2548

2549
// linux_arm64aarch64::lastlog
2550

2551
impl FixedStructTrait for linux_arm64aarch64::lastlog {
2552
    fn fixedstruct_type(&self) -> FixedStructType {
10✔
2553
        FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog
10✔
2554
    }
10✔
2555
    fn size(&self) -> usize {
7✔
2556
        linux_arm64aarch64::LASTLOG_SZ
7✔
2557
    }
7✔
2558

2559
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
2560
        panic!("as_freebsd_x8664_utmpx() called on freebsd_x8664::utmpx");
×
2561
    }
2562
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
9✔
2563
        self
9✔
2564
    }
9✔
2565
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
2566
        panic!("as_linux_arm64aarch64_utmpx() called on freebsd_x8664::utmpx");
×
2567
    }
2568
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
2569
        panic!("as_linux_x86_acct() called on freebsd_x8664::utmpx");
×
2570
    }
2571
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
2572
        panic!("as_linux_x86_acct_v3() called on freebsd_x8664::utmpx");
×
2573
    }
2574
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
2575
        panic!("as_linux_x86_lastlog() called on freebsd_x8664::utmpx");
×
2576
    }
2577
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
2578
        panic!("as_linux_x86_utmpx() called on freebsd_x8664::utmpx");
×
2579
    }
2580
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
2581
        panic!("as_netbsd_x8632_acct() called on freebsd_x8664::utmpx");
×
2582
    }
2583
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
2584
        panic!("as_netbsd_x8632_lastlogx() called on freebsd_x8664::utmpx");
×
2585
    }
2586
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
2587
        panic!("as_netbsd_x8632_utmpx() called on freebsd_x8664::utmpx");
×
2588
    }
2589
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
2590
        panic!("as_netbsd_x8664_lastlog() called on freebsd_x8664::utmpx");
×
2591
    }
2592
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
2593
        panic!("as_netbsd_x8664_lastlogx() called on freebsd_x8664::utmpx");
×
2594
    }
2595
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
2596
        panic!("as_netbsd_x8664_utmp() called on freebsd_x8664::utmpx");
×
2597
    }
2598
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
2599
        panic!("as_netbsd_x8664_utmpx() called on freebsd_x8664::utmpx");
×
2600
    }
2601
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
2602
        panic!("as_openbsd_x86_lastlog() called on freebsd_x8664::utmpx");
×
2603
    }
2604
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
2605
        panic!("as_openbsd_x86_utmp() called on freebsd_x8664::utmpx");
×
2606
    }
2607
}
2608

2609
impl fmt::Debug for linux_arm64aarch64::lastlog {
2610
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
2611
        f.debug_struct("linux_arm64aarch64::lastlog")
2✔
2612
            .field("size", &self.size())
2✔
2613
            .field("ll_time", &self.ll_time)
2✔
2614
            .field("ll_line", &self.ll_line())
2✔
2615
            .field("ll_host", &self.ll_host())
2✔
2616
            .finish()
2✔
2617
    }
2✔
2618
}
2619

2620
// linux_arm64aarch64::utmpx
2621

2622
impl FixedStructTrait for linux_arm64aarch64::utmpx {
2623
    fn fixedstruct_type(&self) -> FixedStructType {
10✔
2624
        FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx
10✔
2625
    }
10✔
2626
    fn size(&self) -> usize {
7✔
2627
        linux_arm64aarch64::UTMPX_SZ
7✔
2628
    }
7✔
2629

2630
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
2631
        panic!("as_freebsd_x8664_utmpx() called on linux_arm64aarch64::utmpx");
×
2632
    }
2633
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
2634
        panic!("as_linux_arm64aarch64_lastlog() called on linux_arm64aarch64::utmpx");
×
2635
    }
2636
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
9✔
2637
        self
9✔
2638
    }
9✔
2639
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
2640
        panic!("as_linux_x86_acct() called on linux_arm64aarch64::utmpx");
×
2641
    }
2642
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
2643
        panic!("as_linux_x86_acct_v3() called on linux_arm64aarch64::utmpx");
×
2644
    }
2645
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
2646
        panic!("as_linux_x86_lastlog() called on linux_arm64aarch64::utmpx");
×
2647
    }
2648
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
2649
        panic!("as_linux_x86_utmpx() called on linux_arm64aarch64::utmpx");
×
2650
    }
2651
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
2652
        panic!("as_netbsd_x8632_acct() called on linux_arm64aarch64::utmpx");
×
2653
    }
2654
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
2655
        panic!("as_netbsd_x8632_lastlogx() called on linux_arm64aarch64::utmpx");
×
2656
    }
2657
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
2658
        panic!("as_netbsd_x8632_utmpx() called on linux_arm64aarch64::utmpx");
×
2659
    }
2660
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
2661
        panic!("as_netbsd_x8664_lastlog() called on linux_arm64aarch64::utmpx");
×
2662
    }
2663
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
2664
        panic!("as_netbsd_x8664_lastlogx() called on linux_arm64aarch64::utmpx");
×
2665
    }
2666
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
2667
        panic!("as_netbsd_x8664_utmp() called on linux_arm64aarch64::utmpx");
×
2668
    }
2669
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
2670
        panic!("as_netbsd_x8664_utmpx() called on linux_arm64aarch64::utmpx");
×
2671
    }
2672
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
2673
        panic!("as_openbsd_x86_lastlog() called on linux_arm64aarch64::utmpx");
×
2674
    }
2675
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
2676
        panic!("as_openbsd_x86_utmp() called on linux_arm64aarch64::utmpx");
×
2677
    }
2678
}
2679

2680
impl fmt::Debug for linux_arm64aarch64::utmpx {
2681
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
2682
        f.debug_struct("linux_arm64aarch64::utmpx")
2✔
2683
            .field("size", &self.size())
2✔
2684
            .field("ut_type", &self.ut_type)
2✔
2685
            .field("ut_pid", &self.ut_pid)
2✔
2686
            .field("ut_line", &self.ut_line())
2✔
2687
            .field("ut_id", &self.ut_id())
2✔
2688
            .field("ut_user", &self.ut_user())
2✔
2689
            .field("ut_host", &self.ut_host())
2✔
2690
            .field("ut_tv.tv_sec", &self.ut_tv.tv_sec)
2✔
2691
            .field("ut_tv.tv_usec", &self.ut_tv.tv_usec)
2✔
2692
            .field("ut_addr_v6", &self.ut_addr_v6)
2✔
2693
            .finish()
2✔
2694
    }
2✔
2695
}
2696

2697
// linux_x86::acct
2698

2699
impl FixedStructTrait for linux_x86::acct {
2700
    fn fixedstruct_type(&self) -> FixedStructType {
2,910✔
2701
        FixedStructType::Fs_Linux_x86_Acct
2,910✔
2702
    }
2,910✔
2703
    fn size(&self) -> usize {
1,167✔
2704
        linux_x86::ACCT_SZ
1,167✔
2705
    }
1,167✔
2706

2707
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
2708
        panic!("as_freebsd_x8664_utmpx() called on linux_x86::acct");
×
2709
    }
2710
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
2711
        panic!("as_linux_arm64aarch64_lastlog() called on linux_x86::acct");
×
2712
    }
2713
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
2714
        panic!("as_linux_arm64aarch64_utmpx() called on linux_x86::acct");
×
2715
    }
2716
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
1,169✔
2717
        self
1,169✔
2718
    }
1,169✔
2719
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
2720
        panic!("as_linux_x86_acct_v3() called on linux_x86::acct");
×
2721
    }
2722
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
2723
        panic!("as_linux_x86_lastlog() called on linux_x86::acct");
×
2724
    }
2725
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
2726
        panic!("as_linux_x86_utmpx() called on linux_x86::acct");
×
2727
    }
2728
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
2729
        panic!("as_netbsd_x8632_acct() called on linux_x86::acct");
×
2730
    }
2731
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
2732
        panic!("as_netbsd_x8632_lastlogx() called on linux_x86::acct");
×
2733
    }
2734
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
2735
        panic!("as_netbsd_x8632_utmpx() called on linux_x86::acct");
×
2736
    }
2737
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
2738
        panic!("as_netbsd_x8664_lastlog() called on linux_x86::acct");
×
2739
    }
2740
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
2741
        panic!("as_netbsd_x8664_lastlogx() called on linux_x86::acct");
×
2742
    }
2743
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
2744
        panic!("as_netbsd_x8664_utmp() called on linux_x86::acct");
×
2745
    }
2746
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
2747
        panic!("as_netbsd_x8664_utmpx() called on linux_x86::acct");
×
2748
    }
2749
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
2750
        panic!("as_openbsd_x86_lastlog() called on linux_x86::acct");
×
2751
    }
2752
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
2753
        panic!("as_openbsd_x86_utmp() called on linux_x86::acct");
×
2754
    }
2755
}
2756

2757
impl fmt::Debug for linux_x86::acct {
2758
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
2759
        f.debug_struct("linux_x86::acct")
2✔
2760
            .field("size", &self.size())
2✔
2761
            .field("ac_flag", &self.ac_flag)
2✔
2762
            .field("ac_uid", &self.ac_uid)
2✔
2763
            .field("ac_gid", &self.ac_gid)
2✔
2764
            .field("ac_tty", &self.ac_tty)
2✔
2765
            .field("ac_btime", &self.ac_btime)
2✔
2766
            .field("ac_utime", &self.ac_utime)
2✔
2767
            .field("ac_stime", &self.ac_stime)
2✔
2768
            .field("ac_etime", &self.ac_etime)
2✔
2769
            .field("ac_mem", &self.ac_mem)
2✔
2770
            .field("ac_io", &self.ac_io)
2✔
2771
            .field("ac_rw", &self.ac_rw)
2✔
2772
            .field("ac_minflt", &self.ac_minflt)
2✔
2773
            .field("ac_majflt", &self.ac_majflt)
2✔
2774
            .field("ac_swaps", &self.ac_swaps)
2✔
2775
            .field("ac_exitcode", &self.ac_exitcode)
2✔
2776
            .field("ac_comm", &self.ac_comm())
2✔
2777
            .finish()
2✔
2778
    }
2✔
2779
}
2780

2781
// linux_x86::acct_v3
2782

2783
impl FixedStructTrait for linux_x86::acct_v3 {
2784
    fn fixedstruct_type(&self) -> FixedStructType {
2,910✔
2785
        FixedStructType::Fs_Linux_x86_Acct_v3
2,910✔
2786
    }
2,910✔
2787
    fn size(&self) -> usize {
1,167✔
2788
        linux_x86::ACCT_V3_SZ
1,167✔
2789
    }
1,167✔
2790

2791
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
2792
        panic!("as_freebsd_x8664_utmpx() called on linux_x86::acct_v3");
×
2793
    }
2794
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
2795
        panic!("as_linux_arm64aarch64_lastlog() called on linux_x86::acct_v3");
×
2796
    }
2797
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
2798
        panic!("as_linux_arm64aarch64_utmpx() called on linux_x86::acct_v3");
×
2799
    }
2800
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
2801
        panic!("as_linux_x86_acct() called on linux_x86::acct_v3");
×
2802
    }
2803
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
1,169✔
2804
        self
1,169✔
2805
    }
1,169✔
2806
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
2807
        panic!("as_linux_x86_lastlog() called on linux_x86::acct_v3");
×
2808
    }
2809
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
2810
        panic!("as_linux_x86_utmpx() called on linux_x86::acct_v3");
×
2811
    }
2812
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
2813
        panic!("as_netbsd_x8632_acct() called on linux_x86::acct_v3");
×
2814
    }
2815
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
2816
        panic!("as_netbsd_x8632_lastlogx() called on linux_x86::acct_v3");
×
2817
    }
2818
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
2819
        panic!("as_netbsd_x8632_utmpx() called on linux_x86::acct_v3");
×
2820
    }
2821
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
2822
        panic!("as_netbsd_x8664_lastlog() called on linux_x86::acct_v3");
×
2823
    }
2824
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
2825
        panic!("as_netbsd_x8664_lastlogx() called on linux_x86::acct_v3");
×
2826
    }
2827
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
2828
        panic!("as_netbsd_x8664_utmp() called on linux_x86::acct_v3");
×
2829
    }
2830
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
2831
        panic!("as_netbsd_x8664_utmpx() called on linux_x86::acct_v3");
×
2832
    }
2833
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
2834
        panic!("as_openbsd_x86_lastlog() called on linux_x86::acct_v3");
×
2835
    }
2836
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
2837
        panic!("as_openbsd_x86_utmp() called on linux_x86::acct_v3");
×
2838
    }
2839
}
2840

2841
impl fmt::Debug for linux_x86::acct_v3 {
2842
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
2843
        f.debug_struct("linux_x86::acct_v3")
2✔
2844
            .field("size", &self.size())
2✔
2845
            .field("ac_flag", &self.ac_flag)
2✔
2846
            .field("ac_tty", &self.ac_tty)
2✔
2847
            .field("ac_exitcode", &self.ac_exitcode)
2✔
2848
            .field("ac_uid", &self.ac_uid)
2✔
2849
            .field("ac_gid", &self.ac_gid)
2✔
2850
            .field("ac_pid", &self.ac_pid)
2✔
2851
            .field("ac_ppid", &self.ac_ppid)
2✔
2852
            .field("ac_btime", &self.ac_btime)
2✔
2853
            .field("ac_etime", &self.ac_etime)
2✔
2854
            .field("ac_utime", &self.ac_utime)
2✔
2855
            .field("ac_stime", &self.ac_stime)
2✔
2856
            .field("ac_mem", &self.ac_mem)
2✔
2857
            .field("ac_io", &self.ac_io)
2✔
2858
            .field("ac_rw", &self.ac_rw)
2✔
2859
            .field("ac_minflt", &self.ac_minflt)
2✔
2860
            .field("ac_majflt", &self.ac_majflt)
2✔
2861
            .field("ac_swaps", &self.ac_swaps)
2✔
2862
            .field("ac_comm", &self.ac_comm())
2✔
2863
            .finish()
2✔
2864
    }
2✔
2865
}
2866

2867
// linux_x86::lastlog
2868

2869
impl FixedStructTrait for linux_x86::lastlog {
2870
    fn fixedstruct_type(&self) -> FixedStructType {
67✔
2871
        FixedStructType::Fs_Linux_x86_Lastlog
67✔
2872
    }
67✔
2873
    fn size(&self) -> usize {
56✔
2874
        linux_x86::LASTLOG_SZ
56✔
2875
    }
56✔
2876

2877
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
2878
        panic!("as_freebsd_x8664_utmpx() called on linux_x86::lastlog");
×
2879
    }
2880
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
2881
        panic!("as_linux_arm64aarch64_lastlog() called on linux_x86::lastlog");
×
2882
    }
2883
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
2884
        panic!("as_linux_arm64aarch64_utmpx() called on linux_x86::lastlog");
×
2885
    }
2886
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
2887
        panic!("as_linux_x86_acct() called on linux_x86::lastlog");
×
2888
    }
2889
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
2890
        panic!("as_linux_x86_acct_v3() called on linux_x86::lastlog");
×
2891
    }
2892
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
45✔
2893
        self
45✔
2894
    }
45✔
2895
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
2896
        panic!("as_linux_x86_utmpx() called on linux_x86::lastlog");
×
2897
    }
2898
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
2899
        panic!("as_netbsd_x8632_acct() called on linux_x86::lastlog");
×
2900
    }
2901
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
2902
        panic!("as_netbsd_x8632_lastlogx() called on linux_x86::lastlog");
×
2903
    }
2904
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
2905
        panic!("as_netbsd_x8632_utmpx() called on linux_x86::lastlog");
×
2906
    }
2907
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
2908
        panic!("as_netbsd_x8664_lastlog() called on linux_x86::lastlog");
×
2909
    }
2910
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
2911
        panic!("as_netbsd_x8664_lastlogx() called on linux_x86::lastlog");
×
2912
    }
2913
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
2914
        panic!("as_netbsd_x8664_utmp() called on linux_x86::lastlog");
×
2915
    }
2916
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
2917
        panic!("as_netbsd_x8664_utmpx() called on linux_x86::lastlog");
×
2918
    }
2919
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
2920
        panic!("as_openbsd_x86_lastlog() called on linux_x86::lastlog");
×
2921
    }
2922
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
2923
        panic!("as_openbsd_x86_utmp() called on linux_x86::lastlog");
×
2924
    }
2925
}
2926

2927
impl fmt::Debug for linux_x86::lastlog {
2928
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16✔
2929
        f.debug_struct("linux_x86::lastlog")
16✔
2930
            .field("size", &self.size())
16✔
2931
            .field("ll_time", &self.ll_time)
16✔
2932
            .field("ll_line", &self.ll_line())
16✔
2933
            .field("ll_host", &self.ll_host())
16✔
2934
            .finish()
16✔
2935
    }
16✔
2936
}
2937

2938
// linux_x86::utmpx
2939

2940
impl FixedStructTrait for linux_x86::utmpx {
2941
    fn fixedstruct_type(&self) -> FixedStructType {
7,689✔
2942
        FixedStructType::Fs_Linux_x86_Utmpx
7,689✔
2943
    }
7,689✔
2944
    fn size(&self) -> usize {
221,712✔
2945
        linux_x86::UTMPX_SZ
221,712✔
2946
    }
221,712✔
2947

2948
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
2949
        panic!("as_freebsd_x8664_utmpx() called on linux_x86::utmpx");
×
2950
    }
2951
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
2952
        panic!("as_linux_arm64aarch64_lastlog() called on linux_x86::utmpx");
×
2953
    }
2954
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
2955
        panic!("as_linux_arm64aarch64_utmpx() called on linux_x86::utmpx");
×
2956
    }
2957
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
2958
        panic!("as_linux_x86_acct() called on linux_x86::utmpx");
×
2959
    }
2960
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
2961
        panic!("as_linux_x86_acct_v3() called on linux_x86::utmpx");
×
2962
    }
2963
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
2964
        panic!("as_linux_x86_lastlog() called on linux_x86::utmpx");
×
2965
    }
2966
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
5,996✔
2967
        self
5,996✔
2968
    }
5,996✔
2969
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
2970
        panic!("as_netbsd_x8632_acct() called on linux_x86::utmpx");
×
2971
    }
2972
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
2973
        panic!("as_netbsd_x8632_lastlogx() called on linux_x86::utmpx");
×
2974
    }
2975
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
2976
        panic!("as_netbsd_x8632_utmpx() called on linux_x86::utmpx");
×
2977
    }
2978
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
2979
        panic!("as_netbsd_x8664_lastlog() called on linux_x86::utmpx");
×
2980
    }
2981
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
2982
        panic!("as_netbsd_x8664_lastlogx() called on linux_x86::utmpx");
×
2983
    }
2984
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
2985
        panic!("as_netbsd_x8664_utmp() called on linux_x86::utmpx");
×
2986
    }
2987
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
2988
        panic!("as_netbsd_x8664_utmpx() called on linux_x86::utmpx");
×
2989
    }
2990
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
2991
        panic!("as_openbsd_x86_lastlog() called on linux_x86::utmpx");
×
2992
    }
2993
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
2994
        panic!("as_openbsd_x86_utmp() called on linux_x86::utmpx");
×
2995
    }
2996
}
2997

2998
impl fmt::Debug for linux_x86::utmpx {
2999
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2,253✔
3000
        let ut_pid_s = match self.ut_type {
2,253✔
3001
            x if x < UT_TYPE_VAL_TO_STR_LEN_i16 && x >= 0 => format!("{} ({})", self.ut_type, UT_TYPE_VAL_TO_STR[self.ut_type as usize]),
2,253✔
3002
            _ => format!("{} (UNKNOWN)", self.ut_type),
4✔
3003
        };
3004
        f.debug_struct("linux_x86::utmpx")
2,253✔
3005
            .field("size", &self.size())
2,253✔
3006
            .field("ut_type", &self.ut_type)
2,253✔
3007
            .field("ut_pid", &format_args!("{}", ut_pid_s))
2,253✔
3008
            .field("ut_line", &self.ut_line())
2,253✔
3009
            .field("ut_id", &self.ut_id())
2,253✔
3010
            .field("ut_user", &self.ut_user())
2,253✔
3011
            .field("ut_host", &self.ut_host())
2,253✔
3012
            .field("ut_exit_e_termination", &self.ut_exit.e_termination)
2,253✔
3013
            .field("ut_exit_e_exit", &self.ut_exit.e_exit)
2,253✔
3014
            .field("ut_session", &self.ut_session)
2,253✔
3015
            .field("ut_tv.tv_sec", &self.ut_tv.tv_sec)
2,253✔
3016
            .field("ut_tv.tv_usec", &self.ut_tv.tv_usec)
2,253✔
3017
            .finish()
2,253✔
3018
    }
2,253✔
3019
}
3020

3021
// netbsd_x8632::acct
3022

3023
impl FixedStructTrait for netbsd_x8632::acct {
3024
    fn fixedstruct_type(&self) -> FixedStructType {
10✔
3025
        FixedStructType::Fs_Netbsd_x8632_Acct
10✔
3026
    }
10✔
3027
    fn size(&self) -> usize {
7✔
3028
        netbsd_x8632::ACCT_SZ
7✔
3029
    }
7✔
3030

3031
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
3032
        panic!("as_freebsd_x8664_utmpx() called on netbsd_x8632::lastlog");
×
3033
    }
3034
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
3035
        panic!("as_linux_arm64aarch64_lastlog() called on netbsd_x8632::lastlog");
×
3036
    }
3037
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
3038
        panic!("as_linux_arm64aarch64_utmpx() called on netbsd_x8632::lastlog");
×
3039
    }
3040
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
3041
        panic!("as_linux_x86_acct() called on netbsd_x8632::lastlog");
×
3042
    }
3043
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
3044
        panic!("as_linux_x86_acct_v3() called on netbsd_x8632::lastlog");
×
3045
    }
3046
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
3047
        panic!("as_linux_x86_lastlog() called on netbsd_x8632::lastlog");
×
3048
    }
3049
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
3050
        panic!("as_linux_x86_utmpx() called on netbsd_x8632::lastlog");
×
3051
    }
3052
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
9✔
3053
        self
9✔
3054
    }
9✔
3055
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
3056
        panic!("as_netbsd_x8632_lastlogx() called on netbsd_x8632::lastlog");
×
3057
    }
3058
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
3059
        panic!("as_netbsd_x8632_utmpx() called on netbsd_x8632::lastlog");
×
3060
    }
3061
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
3062
        panic!("as_netbsd_x8664_lastlog() called on netbsd_x8632::lastlog");
×
3063
    }
3064
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
3065
        panic!("as_netbsd_x8664_lastlogx() called on netbsd_x8632::lastlog");
×
3066
    }
3067
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
3068
        panic!("as_netbsd_x8664_utmp() called on netbsd_x8632::lastlog");
×
3069
    }
3070
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
3071
        panic!("as_netbsd_x8664_utmpx() called on netbsd_x8632::lastlog");
×
3072
    }
3073
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
3074
        panic!("as_openbsd_x86_lastlog() called on netbsd_x8632::lastlog");
×
3075
    }
3076
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
3077
        panic!("as_openbsd_x86_utmp() called on netbsd_x8632::lastlog");
×
3078
    }
3079
}
3080

3081
impl fmt::Debug for netbsd_x8632::acct {
3082
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
3083
        let ac_utime = self.ac_utime;
2✔
3084
        let ac_stime = self.ac_stime;
2✔
3085
        let ac_etime = self.ac_etime;
2✔
3086
        let ac_btime = self.ac_btime;
2✔
3087
        let ac_uid = self.ac_uid;
2✔
3088
        let ac_gid = self.ac_gid;
2✔
3089
        let ac_mem = self.ac_mem;
2✔
3090
        let ac_io = self.ac_io;
2✔
3091
        let ac_tty = self.ac_tty;
2✔
3092
        let ac_flag = self.ac_flag;
2✔
3093
        f.debug_struct("netbsd_x8632::acct")
2✔
3094
            .field("size", &self.size())
2✔
3095
            .field("ac_comm", &self.ac_comm())
2✔
3096
            .field("ac_utime", &ac_utime)
2✔
3097
            .field("ac_stime", &ac_stime)
2✔
3098
            .field("ac_etime", &ac_etime)
2✔
3099
            .field("ac_btime", &ac_btime)
2✔
3100
            .field("ac_uid", &ac_uid)
2✔
3101
            .field("ac_gid", &ac_gid)
2✔
3102
            .field("ac_mem", &ac_mem)
2✔
3103
            .field("ac_io", &ac_io)
2✔
3104
            .field("ac_tty", &ac_tty)
2✔
3105
            .field("ac_flag", &ac_flag)
2✔
3106
            .finish()
2✔
3107
    }
2✔
3108
}
3109

3110
// netbsd_x8632::lastlogx
3111

3112
impl FixedStructTrait for netbsd_x8632::lastlogx {
3113
    fn fixedstruct_type(&self) -> FixedStructType {
10✔
3114
        FixedStructType::Fs_Netbsd_x8632_Lastlogx
10✔
3115
    }
10✔
3116
    fn size(&self) -> usize {
7✔
3117
        netbsd_x8632::LASTLOGX_SZ
7✔
3118
    }
7✔
3119

3120
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
3121
        panic!("as_freebsd_x8664_utmpx() called on netbsd_x8632::lastlogx");
×
3122
    }
3123
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
3124
        panic!("as_linux_arm64aarch64_lastlog() called on netbsd_x8632::lastlogx");
×
3125
    }
3126
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
3127
        panic!("as_linux_arm64aarch64_utmpx() called on netbsd_x8632::lastlogx");
×
3128
    }
3129
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
3130
        panic!("as_linux_x86_acct() called on netbsd_x8632::lastlogx");
×
3131
    }
3132
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
3133
        panic!("as_linux_x86_acct_v3() called on netbsd_x8632::lastlogx");
×
3134
    }
3135
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
3136
        panic!("as_linux_x86_lastlog() called on netbsd_x8632::lastlogx");
×
3137
    }
3138
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
3139
        panic!("as_linux_x86_utmpx() called on netbsd_x8632::lastlogx");
×
3140
    }
3141
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
3142
        panic!("as_netbsd_x8632_acct() called on netbsd_x8632::lastlogx");
×
3143
    }
3144
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
9✔
3145
        self
9✔
3146
    }
9✔
3147
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
3148
        panic!("as_netbsd_x8632_utmpx() called on netbsd_x8632::lastlogx");
×
3149
    }
3150
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
3151
        panic!("as_netbsd_x8664_lastlog() called on netbsd_x8632::lastlogx");
×
3152
    }
3153
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
3154
        panic!("as_netbsd_x8664_lastlogx() called on netbsd_x8632::lastlogx");
×
3155
    }
3156
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
3157
        panic!("as_netbsd_x8664_utmp() called on netbsd_x8632::lastlogx");
×
3158
    }
3159
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
3160
        panic!("as_netbsd_x8664_utmpx() called on netbsd_x8632::lastlogx");
×
3161
    }
3162
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
3163
        panic!("as_openbsd_x86_lastlog() called on netbsd_x8632::lastlogx");
×
3164
    }
3165
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
3166
        panic!("as_openbsd_x86_utmp() called on netbsd_x8632::lastlogx");
×
3167
    }
3168
}
3169

3170
impl fmt::Debug for netbsd_x8632::lastlogx {
3171
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
3172
        // XXX: copy to local to avoid Issue #82523; #rust-lang/rust/82523
3173
        let tv_sec = self.ll_tv.tv_sec;
2✔
3174
        // XXX: copy to local to avoid Issue #82523; #rust-lang/rust/82523
3175
        let tv_usec = self.ll_tv.tv_usec;
2✔
3176
        f.debug_struct("netbsd_x8632::lastlogx")
2✔
3177
            .field("size", &self.size())
2✔
3178
            .field("ll_tv.tv_sec", &tv_sec)
2✔
3179
            .field("ll_tv.tv_usec", &tv_usec)
2✔
3180
            .field("ll_line", &self.ll_line())
2✔
3181
            .field("ll_host", &self.ll_host())
2✔
3182
            .field("ll_ss", &self.ll_ss)
2✔
3183
            .finish()
2✔
3184
    }
2✔
3185
}
3186

3187
// netbsd_x8632::utmpx
3188

3189
impl FixedStructTrait for netbsd_x8632::utmpx {
3190
    fn fixedstruct_type(&self) -> FixedStructType {
10✔
3191
        FixedStructType::Fs_Netbsd_x8632_Utmpx
10✔
3192
    }
10✔
3193
    fn size(&self) -> usize {
7✔
3194
        netbsd_x8632::UTMPX_SZ
7✔
3195
    }
7✔
3196

3197
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
3198
        panic!("as_freebsd_x8664_utmpx() called on netbsd_x8632::utmpx");
×
3199
    }
3200
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
3201
        panic!("as_linux_arm64aarch64_lastlog() called on netbsd_x8632::utmpx");
×
3202
    }
3203
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
3204
        panic!("as_linux_arm64aarch64_utmpx() called on netbsd_x8632::utmpx");
×
3205
    }
3206
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
3207
        panic!("as_linux_x86_acct() called on netbsd_x8632::utmpx");
×
3208
    }
3209
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
3210
        panic!("as_linux_x86_acct_v3() called on netbsd_x8632::utmpx");
×
3211
    }
3212
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
3213
        panic!("as_linux_x86_lastlog() called on netbsd_x8632::utmpx");
×
3214
    }
3215
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
3216
        panic!("as_linux_x86_utmpx() called on netbsd_x8632::utmpx");
×
3217
    }
3218
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
3219
        panic!("as_netbsd_x8632_acct() called on netbsd_x8632::utmpx");
×
3220
    }
3221
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
3222
        panic!("as_netbsd_x8632_lastlogx() called on netbsd_x8632::utmpx");
×
3223
    }
3224
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
9✔
3225
        self
9✔
3226
    }
9✔
3227
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
3228
        panic!("as_netbsd_x8664_lastlog() called on netbsd_x8632::utmpx");
×
3229
    }
3230
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
3231
        panic!("as_netbsd_x8664_lastlogx() called on netbsd_x8632::utmpx");
×
3232
    }
3233
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
3234
        panic!("as_netbsd_x8664_utmp() called on netbsd_x8632::utmpx");
×
3235
    }
3236
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
3237
        panic!("as_netbsd_x8664_utmpx() called on netbsd_x8632::utmpx");
×
3238
    }
3239
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
3240
        panic!("as_openbsd_x86_lastlog() called on netbsd_x8632::utmpx");
×
3241
    }
3242
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
3243
        panic!("as_openbsd_x86_utmp() called on netbsd_x8632::utmpx");
×
3244
    }
3245
}
3246

3247
impl fmt::Debug for netbsd_x8632::utmpx {
3248
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
3249
        // XXX: copy to local to avoid Issue #82523; #rust-lang/rust/82523
3250
        let tv_sec = self.ut_tv.tv_sec;
2✔
3251
        // XXX: copy to local to avoid Issue #82523; #rust-lang/rust/82523
3252
        let tv_usec = self.ut_tv.tv_usec;
2✔
3253
        f.debug_struct("netbsd_x8632::utmpx")
2✔
3254
            .field("size", &self.size())
2✔
3255
            .field("ut_name", &self.ut_name())
2✔
3256
            .field("ut_id", &self.ut_id())
2✔
3257
            .field("ut_line", &self.ut_line())
2✔
3258
            .field("ut_host", &self.ut_host())
2✔
3259
            .field("ut_session", &self.ut_session)
2✔
3260
            .field("ut_type", &self.ut_type)
2✔
3261
            .field("ut_pid", &self.ut_pid)
2✔
3262
            .field("ut_exit.e_termination", &self.ut_exit.e_termination)
2✔
3263
            .field("ut_exit.e_exit", &self.ut_exit.e_exit)
2✔
3264
            .field("ut_ss", &self.ut_ss)
2✔
3265
            .field("ut_tv.tv_sec", &tv_sec)
2✔
3266
            .field("ut_tv.tv_usec", &tv_usec)
2✔
3267
            .field("ut_pad", &self.ut_pad)
2✔
3268
            .finish()
2✔
3269
    }
2✔
3270
}
3271

3272
// netbsd_x8664::lastlog
3273

3274
impl FixedStructTrait for netbsd_x8664::lastlog {
3275
    fn fixedstruct_type(&self) -> FixedStructType {
2,910✔
3276
        FixedStructType::Fs_Netbsd_x8664_Lastlog
2,910✔
3277
    }
2,910✔
3278
    fn size(&self) -> usize {
1,167✔
3279
        netbsd_x8664::LASTLOG_SZ
1,167✔
3280
    }
1,167✔
3281

3282
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
3283
        panic!("as_freebsd_x8664_utmpx() called on netbsd_x8664::lastlog");
×
3284
    }
3285
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
3286
        panic!("as_linux_arm64aarch64_lastlog() called on netbsd_x8664::lastlog");
×
3287
    }
3288
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
3289
        panic!("as_linux_arm64aarch64_utmpx() called on netbsd_x8664::lastlog");
×
3290
    }
3291
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
3292
        panic!("as_linux_x86_acct() called on netbsd_x8664::lastlog");
×
3293
    }
3294
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
3295
        panic!("as_linux_x86_acct_v3() called on netbsd_x8664::lastlog");
×
3296
    }
3297
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
3298
        panic!("as_linux_x86_lastlog() called on netbsd_x8664::lastlog");
×
3299
    }
3300
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
3301
        panic!("as_linux_x86_utmpx() called on netbsd_x8664::lastlog");
×
3302
    }
3303
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
3304
        panic!("as_netbsd_x8632_acct() called on netbsd_x8664::lastlog");
×
3305
    }
3306
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
3307
        panic!("as_netbsd_x8632_lastlogx() called on netbsd_x8664::lastlog");
×
3308
    }
3309
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
3310
        panic!("as_netbsd_x8632_utmpx() called on netbsd_x8664::lastlog");
×
3311
    }
3312
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
1,169✔
3313
        self
1,169✔
3314
    }
1,169✔
3315
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
3316
        panic!("as_netbsd_x8664_lastlogx() called on netbsd_x8664::lastlog");
×
3317
    }
3318
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
3319
        panic!("as_netbsd_x8664_utmp() called on netbsd_x8664::lastlog");
×
3320
    }
3321
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
3322
        panic!("as_netbsd_x8664_utmpx() called on netbsd_x8664::lastlog");
×
3323
    }
3324
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
3325
        panic!("as_openbsd_x86_lastlog() called on netbsd_x8664::lastlog");
×
3326
    }
3327
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
3328
        panic!("as_openbsd_x86_utmp() called on netbsd_x8664::lastlog");
×
3329
    }
3330
}
3331

3332
impl fmt::Debug for netbsd_x8664::lastlog {
3333
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
3334
        f.debug_struct("netbsd_x8664::lastlog")
2✔
3335
            .field("size", &self.size())
2✔
3336
            .field("ll_time", &self.ll_time)
2✔
3337
            .field("ll_line", &self.ll_line())
2✔
3338
            .field("ll_host", &self.ll_host())
2✔
3339
            .finish()
2✔
3340
    }
2✔
3341
}
3342

3343
// netbsd_x8664::lastlogx
3344

3345
impl FixedStructTrait for netbsd_x8664::lastlogx {
3346
    fn fixedstruct_type(&self) -> FixedStructType {
5✔
3347
        FixedStructType::Fs_Netbsd_x8664_Lastlogx
5✔
3348
    }
5✔
3349
    fn size(&self) -> usize {
5✔
3350
        netbsd_x8664::LASTLOGX_SZ
5✔
3351
    }
5✔
3352

3353
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
3354
        panic!("as_freebsd_x8664_utmpx() called on netbsd_x8664::lastlogx");
×
3355
    }
3356
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
3357
        panic!("as_linux_arm64aarch64_lastlog() called on netbsd_x8664::lastlogx");
×
3358
    }
3359
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
3360
        panic!("as_linux_arm64aarch64_utmpx() called on netbsd_x8664::lastlogx");
×
3361
    }
3362
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
3363
        panic!("as_linux_x86_acct() called on netbsd_x8664::lastlogx");
×
3364
    }
3365
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
3366
        panic!("as_linux_x86_acct_v3() called on netbsd_x8664::lastlogx");
×
3367
    }
3368
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
3369
        panic!("as_linux_x86_lastlog() called on netbsd_x8664::lastlogx");
×
3370
    }
3371
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
3372
        panic!("as_linux_x86_utmpx() called on netbsd_x8664::lastlogx");
×
3373
    }
3374
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
3375
        panic!("as_netbsd_x8632_acct() called on netbsd_x8664::lastlogx");
×
3376
    }
3377
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
3378
        panic!("as_netbsd_x8632_lastlogx() called on netbsd_x8664::lastlogx");
×
3379
    }
3380
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
3381
        panic!("as_netbsd_x8632_utmpx() called on netbsd_x8664::lastlogx");
×
3382
    }
3383
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
3384
        panic!("as_netbsd_x8664_lastlog() called on netbsd_x8664::lastlogx");
×
3385
    }
3386
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
5✔
3387
        self
5✔
3388
    }
5✔
3389
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
3390
        panic!("as_netbsd_x8664_utmp() called on netbsd_x8664::lastlogx");
×
3391
    }
3392
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
3393
        panic!("as_netbsd_x8664_utmpx() called on netbsd_x8664::lastlogx");
×
3394
    }
3395
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
3396
        panic!("as_openbsd_x86_lastlog() called on netbsd_x8664::lastlogx");
×
3397
    }
3398
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
3399
        panic!("as_openbsd_x86_utmp() called on netbsd_x8664::lastlogx");
×
3400
    }
3401
}
3402

3403
impl fmt::Debug for netbsd_x8664::lastlogx {
3404
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1✔
3405
        f.debug_struct("netbsd_x8664::lastlogx")
1✔
3406
            .field("size", &self.size())
1✔
3407
            .field("ll_tv.tv_sec", &self.ll_tv.tv_sec)
1✔
3408
            .field("ll_tv.tv_usec", &self.ll_tv.tv_usec)
1✔
3409
            .field("ll_line", &self.ll_line())
1✔
3410
            .field("ll_host", &self.ll_host())
1✔
3411
            .field("ll_ss", &self.ll_ss)
1✔
3412
            .finish()
1✔
3413
    }
1✔
3414
}
3415

3416
// netbsd_x8664::utmp
3417

3418
impl FixedStructTrait for netbsd_x8664::utmp {
3419
    fn fixedstruct_type(&self) -> FixedStructType {
10✔
3420
        FixedStructType::Fs_Netbsd_x8664_Utmp
10✔
3421
    }
10✔
3422
    fn size(&self) -> usize {
7✔
3423
        netbsd_x8664::UTMP_SZ
7✔
3424
    }
7✔
3425

3426
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
3427
        panic!("as_freebsd_x8664_utmpx() called on netbsd_x8664::utmp");
×
3428
    }
3429
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
3430
        panic!("as_linux_arm64aarch64_lastlog() called on netbsd_x8664::utmp");
×
3431
    }
3432
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
3433
        panic!("as_linux_arm64aarch64_utmpx() called on netbsd_x8664::utmp");
×
3434
    }
3435
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
3436
        panic!("as_linux_x86_acct() called on netbsd_x8664::utmp");
×
3437
    }
3438
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
3439
        panic!("as_linux_x86_acct_v3() called on netbsd_x8664::utmp");
×
3440
    }
3441
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
3442
        panic!("as_linux_x86_lastlog() called on netbsd_x8664::utmp");
×
3443
    }
3444
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
3445
        panic!("as_linux_x86_utmpx() called on netbsd_x8664::utmp");
×
3446
    }
3447
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
3448
        panic!("as_netbsd_x8632_acct() called on netbsd_x8664::utmp");
×
3449
    }
3450
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
3451
        panic!("as_netbsd_x8632_lastlogx() called on netbsd_x8664::utmp");
×
3452
    }
3453
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
3454
        panic!("as_netbsd_x8632_utmpx() called on netbsd_x8664::utmp");
×
3455
    }
3456
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
3457
        panic!("as_netbsd_x8664_lastlog() called on netbsd_x8664::utmp");
×
3458
    }
3459
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
3460
        panic!("as_netbsd_x8664_lastlogx() called on netbsd_x8664::utmp");
×
3461
    }
3462
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
9✔
3463
        self
9✔
3464
    }
9✔
3465
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
3466
        panic!("as_netbsd_x8664_utmpx() called on netbsd_x8664::utmp");
×
3467
    }
3468
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
3469
        panic!("as_openbsd_x86_lastlog() called on netbsd_x8664::utmp");
×
3470
    }
3471
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
3472
        panic!("as_openbsd_x86_utmp() called on netbsd_x8664::utmp");
×
3473
    }
3474
}
3475

3476
impl fmt::Debug for netbsd_x8664::utmp {
3477
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
3478
        f.debug_struct("netbsd_x8664::utmp")
2✔
3479
            .field("size", &self.size())
2✔
3480
            .field("ut_line", &self.ut_line())
2✔
3481
            .field("ut_name", &self.ut_name())
2✔
3482
            .field("ut_host", &self.ut_host())
2✔
3483
            .field("ut_time", &self.ut_time)
2✔
3484
            .finish()
2✔
3485
    }
2✔
3486
}
3487

3488
// netbsd_x8664::utmpx
3489

3490
impl FixedStructTrait for netbsd_x8664::utmpx {
3491
    fn fixedstruct_type(&self) -> FixedStructType {
10✔
3492
        FixedStructType::Fs_Netbsd_x8664_Utmpx
10✔
3493
    }
10✔
3494
    fn size(&self) -> usize {
7✔
3495
        netbsd_x8664::UTMPX_SZ
7✔
3496
    }
7✔
3497

3498
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
3499
        panic!("as_freebsd_x8664_utmpx() called on netbsd_x8664::utmpx");
×
3500
    }
3501
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
3502
        panic!("as_linux_arm64aarch64_lastlog() called on netbsd_x8664::utmpx");
×
3503
    }
3504
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
3505
        panic!("as_linux_arm64aarch64_utmpx() called on netbsd_x8664::utmpx");
×
3506
    }
3507
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
3508
        panic!("as_linux_x86_acct() called on netbsd_x8664::utmpx");
×
3509
    }
3510
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
3511
        panic!("as_linux_x86_acct_v3() called on netbsd_x8664::utmpx");
×
3512
    }
3513
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
3514
        panic!("as_linux_x86_lastlog() called on netbsd_x8664::utmpx");
×
3515
    }
3516
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
3517
        panic!("as_linux_x86_utmpx() called on netbsd_x8664::utmpx");
×
3518
    }
3519
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
3520
        panic!("as_netbsd_x8632_acct() called on netbsd_x8664::utmpx");
×
3521
    }
3522
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
3523
        panic!("as_netbsd_x8632_lastlogx() called on netbsd_x8664::utmpx");
×
3524
    }
3525
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
3526
        panic!("as_netbsd_x8632_utmpx() called on netbsd_x8664::utmpx");
×
3527
    }
3528
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
3529
        panic!("as_netbsd_x8664_lastlog() called on netbsd_x8664::utmpx");
×
3530
    }
3531
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
3532
        panic!("as_netbsd_x8664_lastlogx() called on netbsd_x8664::utmpx");
×
3533
    }
3534
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
3535
        panic!("as_netbsd_x8664_utmp() called on netbsd_x8664::utmpx");
×
3536
    }
3537
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
9✔
3538
        self
9✔
3539
    }
9✔
3540
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
3541
        panic!("as_openbsd_x86_lastlog() called on netbsd_x8664::utmpx");
×
3542
    }
3543
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
3544
        panic!("as_openbsd_x86_utmp() called on netbsd_x8664::utmpx");
×
3545
    }
3546
}
3547

3548
impl fmt::Debug for netbsd_x8664::utmpx {
3549
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
3550
        f.debug_struct("netbsd_x8664::utmpx")
2✔
3551
            .field("size", &self.size())
2✔
3552
            .field("ut_user", &self.ut_user())
2✔
3553
            .field("ut_id", &self.ut_id())
2✔
3554
            .field("ut_line", &self.ut_line())
2✔
3555
            .field("ut_host", &self.ut_host())
2✔
3556
            .field("ut_session", &self.ut_session)
2✔
3557
            .field("ut_type", &self.ut_type)
2✔
3558
            .field("ut_pid", &self.ut_pid)
2✔
3559
            .field("ut_exit.e_termination", &self.ut_exit.e_termination)
2✔
3560
            .field("ut_exit.e_exit", &self.ut_exit.e_exit)
2✔
3561
            .field("ut_tv.tv_sec", &self.ut_tv.tv_sec)
2✔
3562
            .field("ut_tv.tv_usec", &self.ut_tv.tv_usec)
2✔
3563
            .finish()
2✔
3564
    }
2✔
3565
}
3566

3567
// openbsd_x86::lastlog
3568

3569
impl FixedStructTrait for openbsd_x86::lastlog {
3570
    fn fixedstruct_type(&self) -> FixedStructType {
10✔
3571
        FixedStructType::Fs_Openbsd_x86_Lastlog
10✔
3572
    }
10✔
3573
    fn size(&self) -> usize {
7✔
3574
        openbsd_x86::LASTLOG_SZ
7✔
3575
    }
7✔
3576
    
3577
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
3578
        panic!("as_freebsd_x8664_utmpx() called on openbsd_x86::lastlog");
×
3579
    }
3580
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
3581
        panic!("as_linux_arm64aarch64_lastlog() called on openbsd_x86::lastlog");
×
3582
    }
3583
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
3584
        panic!("as_linux_arm64aarch64_utmpx() called on openbsd_x86::lastlog");
×
3585
    }
3586
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
3587
        panic!("as_linux_x86_acct() called on openbsd_x86::lastlog");
×
3588
    }
3589
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
3590
        panic!("as_linux_x86_acct_v3() called on openbsd_x86::lastlog");
×
3591
    }
3592
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
3593
        panic!("as_linux_x86_lastlog() called on openbsd_x86::lastlog");
×
3594
    }
3595
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
3596
        panic!("as_linux_x86_utmpx() called on openbsd_x86::lastlog");
×
3597
    }
3598
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
3599
        panic!("as_netbsd_x8632_acct() called on openbsd_x86::lastlog");
×
3600
    }
3601
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
3602
        panic!("as_netbsd_x8632_lastlogx() called on openbsd_x86::lastlog");
×
3603
    }
3604
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
3605
        panic!("as_netbsd_x8632_utmpx() called on openbsd_x86::lastlog");
×
3606
    }
3607
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
3608
        panic!("as_netbsd_x8664_lastlog() called on openbsd_x86::lastlog");
×
3609
    }
3610
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
3611
        panic!("as_netbsd_x8664_lastlogx() called on openbsd_x86::lastlog");
×
3612
    }
3613
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
3614
        panic!("as_netbsd_x8664_utmp() called on openbsd_x86::lastlog");
×
3615
    }
3616
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
3617
        panic!("as_netbsd_x8664_utmpx() called on openbsd_x86::lastlog");
×
3618
    }
3619
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
9✔
3620
        self
9✔
3621
    }
9✔
3622
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
×
3623
        panic!("as_openbsd_x86_utmp() called on openbsd_x86::lastlog");
×
3624
    }
3625
}
3626

3627
impl fmt::Debug for openbsd_x86::lastlog {
3628
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
3629
        f.debug_struct("openbsd_x86::lastlog")
2✔
3630
            .field("size", &self.size())
2✔
3631
            .field("ll_time", &self.ll_time)
2✔
3632
            .field("ll_line", &self.ll_line())
2✔
3633
            .field("ll_host", &self.ll_host())
2✔
3634
            .finish()
2✔
3635
    }
2✔
3636
}
3637

3638
// openbsd_x86::utmp
3639

3640
impl FixedStructTrait for openbsd_x86::utmp {
3641
    fn fixedstruct_type(&self) -> FixedStructType {
10✔
3642
        FixedStructType::Fs_Openbsd_x86_Utmp
10✔
3643
    }
10✔
3644
    fn size(&self) -> usize {
7✔
3645
        openbsd_x86::UTMP_SZ
7✔
3646
    }
7✔
3647
    
3648
    fn as_freebsd_x8664_utmpx(&self) -> &freebsd_x8664::utmpx {
×
3649
        panic!("as_freebsd_x8664_utmpx() called on openbsd_x86::utmp");
×
3650
    }
3651
    fn as_linux_arm64aarch64_lastlog(&self) -> &linux_arm64aarch64::lastlog {
×
3652
        panic!("as_linux_arm64aarch64_lastlog() called on openbsd_x86::utmp");
×
3653
    }
3654
    fn as_linux_arm64aarch64_utmpx(&self) -> &linux_arm64aarch64::utmpx {
×
3655
        panic!("as_linux_arm64aarch64_utmpx() called on openbsd_x86::utmp");
×
3656
    }
3657
    fn as_linux_x86_acct(&self) -> &linux_x86::acct {
×
3658
        panic!("as_linux_x86_acct() called on openbsd_x86::utmp");
×
3659
    }
3660
    fn as_linux_x86_acct_v3(&self) -> &linux_x86::acct_v3 {
×
3661
        panic!("as_linux_x86_acct_v3() called on openbsd_x86::utmp");
×
3662
    }
3663
    fn as_linux_x86_lastlog(&self) -> &linux_x86::lastlog {
×
3664
        panic!("as_linux_x86_lastlog() called on openbsd_x86::utmp");
×
3665
    }
3666
    fn as_linux_x86_utmpx(&self) -> &linux_x86::utmpx {
×
3667
        panic!("as_linux_x86_utmpx() called on openbsd_x86::utmp");
×
3668
    }
3669
    fn as_netbsd_x8632_acct(&self) -> &netbsd_x8632::acct {
×
3670
        panic!("as_netbsd_x8632_acct() called on openbsd_x86::utmp");
×
3671
    }
3672
    fn as_netbsd_x8632_lastlogx(&self) -> &netbsd_x8632::lastlogx {
×
3673
        panic!("as_netbsd_x8632_lastlogx() called on openbsd_x86::utmp");
×
3674
    }
3675
    fn as_netbsd_x8632_utmpx(&self) -> &netbsd_x8632::utmpx {
×
3676
        panic!("as_netbsd_x8632_utmpx() called on openbsd_x86::utmp");
×
3677
    }
3678
    fn as_netbsd_x8664_lastlog(&self) -> &netbsd_x8664::lastlog {
×
3679
        panic!("as_netbsd_x8664_lastlog() called on openbsd_x86::utmp");
×
3680
    }
3681
    fn as_netbsd_x8664_lastlogx(&self) -> &netbsd_x8664::lastlogx {
×
3682
        panic!("as_netbsd_x8664_lastlogx() called on openbsd_x86::utmp");
×
3683
    }
3684
    fn as_netbsd_x8664_utmp(&self) -> &netbsd_x8664::utmp {
×
3685
        panic!("as_netbsd_x8664_utmp() called on openbsd_x86::utmp");
×
3686
    }
3687
    fn as_netbsd_x8664_utmpx(&self) -> &netbsd_x8664::utmpx {
×
3688
        panic!("as_netbsd_x8664_utmpx() called on openbsd_x86::utmp");
×
3689
    }
3690
    fn as_openbsd_x86_lastlog(&self) -> &openbsd_x86::lastlog {
×
3691
        panic!("as_openbsd_x86_lastlog() called on openbsd_x86::utmp");
×
3692
    }
3693
    fn as_openbsd_x86_utmp(&self) -> &openbsd_x86::utmp {
9✔
3694
        self
9✔
3695
    }
9✔
3696
}
3697

3698
impl fmt::Debug for openbsd_x86::utmp {
3699
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2✔
3700
        f.debug_struct("openbsd_x86::utmp")
2✔
3701
            .field("size", &self.size())
2✔
3702
            .field("ut_line", &self.ut_line())
2✔
3703
            .field("ut_name", &self.ut_name())
2✔
3704
            .field("ut_host", &self.ut_host())
2✔
3705
            .field("ut_time", &self.ut_time)
2✔
3706
            .finish()
2✔
3707
    }
2✔
3708
}
3709

3710
pub (crate) type FixedStructTypeSet = HashMap<FixedStructType, Score>;
3711

3712
/// return all possible [`FixedStructType`] types based on the passed `filesz`.
3713
/// Give a score bonus to matching `FileTypeFixedStruct` types.
3714
pub(crate) fn filesz_to_types(filesz: FileSz, file_type_fixed_struct: &FileTypeFixedStruct)
198✔
3715
    -> Option<FixedStructTypeSet>
198✔
3716
{
3717
    defn!("({:?}, {:?})", filesz, file_type_fixed_struct);
198✔
3718

3719
    if filesz == 0 {
198✔
3720
        defx!("return None; filesz==0");
×
3721
        return None;
×
3722
    }
198✔
3723

3724
    let mut set = FixedStructTypeSet::new();
198✔
3725

3726
    const BONUS: Score = 15;
3727

3728
    // if the given `FileTypeFixedStruct` matches the size offset then
3729
    // it gets a bonus score.
3730
    match file_type_fixed_struct {
198✔
3731
        FileTypeFixedStruct::Acct => {
3732
            if filesz % linux_x86::ACCT_SZ_FO == 0 {
×
3733
                set.insert(FixedStructType::Fs_Linux_x86_Acct, BONUS);
×
3734
            }
×
3735
            if filesz % netbsd_x8632::ACCT_SZ_FO == 0 {
×
3736
                set.insert(FixedStructType::Fs_Netbsd_x8632_Acct, BONUS);
×
3737
            }
×
3738
        }
3739
        FileTypeFixedStruct::AcctV3 => {
3740
            if filesz % linux_x86::ACCT_V3_SZ_FO == 0 {
×
3741
                set.insert(FixedStructType::Fs_Linux_x86_Acct_v3, BONUS);
×
3742
            }
×
3743
        }
3744
        FileTypeFixedStruct::Lastlog => {
3745
            if filesz % linux_arm64aarch64::LASTLOG_SZ_FO == 0 {
2✔
3746
                set.insert(FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog, BONUS);
×
3747
            }
2✔
3748
            if filesz % linux_x86::LASTLOG_SZ_FO == 0 {
2✔
3749
                set.insert(FixedStructType::Fs_Linux_x86_Lastlog, BONUS);
2✔
3750
            }
2✔
3751
            if filesz % netbsd_x8664::LASTLOG_SZ_FO == 0 {
2✔
3752
                set.insert(FixedStructType::Fs_Netbsd_x8664_Lastlog, BONUS);
×
3753
            }
2✔
3754
            if filesz % openbsd_x86::LASTLOG_SZ_FO == 0 {
2✔
3755
                set.insert(FixedStructType::Fs_Openbsd_x86_Lastlog, BONUS);
×
3756
            }
2✔
3757
        }
3758
        FileTypeFixedStruct::Lastlogx => {
3759
            if filesz % netbsd_x8632::LASTLOGX_SZ_FO == 0 {
×
3760
                set.insert(FixedStructType::Fs_Netbsd_x8632_Lastlogx, BONUS);
×
3761
            }
×
3762
        }
3763
        FileTypeFixedStruct::Utmp => {
3764
            if filesz % netbsd_x8664::UTMP_SZ_FO == 0 {
70✔
3765
                set.insert(FixedStructType::Fs_Netbsd_x8664_Utmp, BONUS);
×
3766
            }
70✔
3767
            if filesz % openbsd_x86::UTMP_SZ_FO == 0 {
70✔
3768
                set.insert(FixedStructType::Fs_Openbsd_x86_Utmp, BONUS);
×
3769
            }
70✔
3770
        }
3771
        FileTypeFixedStruct::Utmpx => {
3772
            if filesz % freebsd_x8664::UTMPX_SZ_FO == 0 {
126✔
3773
                set.insert(FixedStructType::Fs_Freebsd_x8664_Utmpx, BONUS);
×
3774
            }
126✔
3775
            if filesz % linux_arm64aarch64::UTMPX_SZ_FO == 0 {
126✔
3776
                set.insert(FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx, BONUS);
×
3777
            }
126✔
3778
            if filesz % linux_x86::UTMPX_SZ_FO == 0 {
126✔
3779
                set.insert(FixedStructType::Fs_Linux_x86_Utmpx, BONUS);
121✔
3780
            }
121✔
3781

3782
            if filesz % netbsd_x8632::UTMPX_SZ_FO == 0 {
126✔
3783
                set.insert(FixedStructType::Fs_Netbsd_x8632_Utmpx, BONUS);
×
3784
            }
126✔
3785
            if filesz % netbsd_x8664::UTMPX_SZ_FO == 0 {
126✔
3786
                set.insert(FixedStructType::Fs_Netbsd_x8664_Utmpx, BONUS);
×
3787
            }
126✔
3788
        }
3789
    }
3790

3791
    // try _all_ types anyway; the file naming varies widely and follows
3792
    // general patterns but is not strict.
3793

3794
    if filesz % freebsd_x8664::UTMPX_SZ_FO == 0 {
198✔
3795
        set.entry(FixedStructType::Fs_Freebsd_x8664_Utmpx).or_insert(0);
×
3796
    }
198✔
3797
    if filesz % linux_arm64aarch64::LASTLOG_SZ_FO == 0 {
198✔
3798
        set.entry(FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog).or_insert(0);
×
3799
    }
198✔
3800
    if filesz % linux_arm64aarch64::UTMPX_SZ_FO == 0 {
198✔
3801
        set.entry(FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx).or_insert(0);
×
3802
    }
198✔
3803
    if filesz % linux_x86::ACCT_SZ_FO == 0 {
198✔
3804
        set.entry(FixedStructType::Fs_Linux_x86_Acct).or_insert(0);
191✔
3805
    }
191✔
3806
    if filesz % linux_x86::ACCT_V3_SZ_FO == 0 {
198✔
3807
        set.entry(FixedStructType::Fs_Linux_x86_Acct_v3).or_insert(0);
191✔
3808
    }
191✔
3809
    if filesz % linux_x86::LASTLOG_SZ_FO == 0 {
198✔
3810
        set.entry(FixedStructType::Fs_Linux_x86_Lastlog).or_insert(0);
7✔
3811
    }
191✔
3812
    if filesz % linux_x86::UTMPX_SZ_FO == 0 {
198✔
3813
        set.entry(FixedStructType::Fs_Linux_x86_Utmpx).or_insert(0);
191✔
3814
    }
191✔
3815
    if filesz % netbsd_x8632::ACCT_SZ_FO == 0 {
198✔
3816
        set.entry(FixedStructType::Fs_Netbsd_x8632_Acct).or_insert(0);
×
3817
    }
198✔
3818
    if filesz % netbsd_x8632::LASTLOGX_SZ_FO == 0 {
198✔
3819
        set.entry(FixedStructType::Fs_Netbsd_x8632_Lastlogx).or_insert(0);
×
3820
    }
198✔
3821
    if filesz % netbsd_x8632::UTMPX_SZ_FO == 0 {
198✔
3822
        set.entry(FixedStructType::Fs_Netbsd_x8632_Utmpx).or_insert(0);
×
3823
    }
198✔
3824
    if filesz % netbsd_x8664::LASTLOG_SZ_FO == 0 {
198✔
3825
        set.entry(FixedStructType::Fs_Netbsd_x8664_Lastlog).or_insert(0);
191✔
3826
    }
191✔
3827
    if filesz % netbsd_x8664::UTMP_SZ_FO == 0 {
198✔
3828
        set.entry(FixedStructType::Fs_Netbsd_x8664_Utmp).or_insert(0);
×
3829
    }
198✔
3830
    if filesz % netbsd_x8664::UTMPX_SZ_FO == 0 {
198✔
3831
        set.entry(FixedStructType::Fs_Netbsd_x8664_Utmpx).or_insert(0);
×
3832
    }
198✔
3833
    if filesz % openbsd_x86::LASTLOG_SZ_FO == 0 {
198✔
3834
        set.entry(FixedStructType::Fs_Openbsd_x86_Lastlog).or_insert(0);
×
3835
    }
198✔
3836
    if filesz % openbsd_x86::UTMP_SZ_FO == 0 {
198✔
3837
        set.entry(FixedStructType::Fs_Openbsd_x86_Utmp).or_insert(0);
×
3838
    }
198✔
3839

3840
    if set.is_empty() {
198✔
3841
        defx!("return None; set.is_empty");
×
3842
        return None;
×
3843
    }
198✔
3844

3845
    defx!("return {} types: {:?}", set.len(), set);
198✔
3846

3847
    Some(set)
198✔
3848
}
198✔
3849

3850
/// An entry for [pointing to a fixed-size C struct] with additional derived
3851
/// information.
3852
///
3853
/// [pointing to a fixed-size C struct]: self::FixedStructTrait
3854
pub struct FixedStruct
3855
{
3856
    /// A pointer to underlying fixed-sized structure entry data.
3857
    pub fixedstructptr: FixedStructDynPtr,
3858
    /// The `fixedstructtype` determines the runtime dispatching of various
3859
    /// methods specific to the fixed-sized structure type.
3860
    pub fixedstructtype: FixedStructType,
3861
    /// `FileTypeFixedStruct` is library-wide type passed in from the caller
3862
    /// It is used as a hint of the originating file.
3863
    pub filetypefixedstruct: FileTypeFixedStruct,
3864
    /// The byte offset into the file where the fixed-sized structure data
3865
    /// begins.
3866
    pub fileoffset: FileOffset,
3867
    /// The derived `DateTimeL` instance using function
3868
    /// [`convert_tvpair_to_datetime`].
3869
    dt: DateTimeL,
3870
    /// The derived tv_pair, equivalent to `dt` but as a `tv_sec` (seconds) and
3871
    /// `tv_usec` (fractional microseconds) pair.
3872
    /// Used early in the `FixedStruct` lifecycle for fast checking of
3873
    /// an entry's datetime without the conversion.
3874
    tv_pair: tv_pair_type,
3875
}
3876

3877
pub fn copy_fixedstructptr(entry: &FixedStructDynPtr) -> FixedStructDynPtr {
×
3878
    match entry.fixedstruct_type() {
×
3879
        FixedStructType::Fs_Freebsd_x8664_Utmpx => {
3880
            Box::new(*entry.as_freebsd_x8664_utmpx())
×
3881
        }
3882
        FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => {
3883
            Box::new(*entry.as_linux_arm64aarch64_lastlog())
×
3884
        }
3885
        FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => {
3886
            Box::new(*entry.as_linux_arm64aarch64_utmpx())
×
3887
        }
3888
        FixedStructType::Fs_Linux_x86_Acct => {
3889
            Box::new(*entry.as_linux_x86_acct())
×
3890
        }
3891
        FixedStructType::Fs_Linux_x86_Acct_v3 => {
3892
            Box::new(*entry.as_linux_x86_acct_v3())
×
3893
        }
3894
        FixedStructType::Fs_Linux_x86_Lastlog => {
3895
            Box::new(*entry.as_linux_x86_lastlog())
×
3896
        }
3897
        FixedStructType::Fs_Linux_x86_Utmpx => {
3898
            Box::new(*entry.as_linux_x86_utmpx())
×
3899
        }
3900
        FixedStructType::Fs_Netbsd_x8632_Acct => {
3901
            Box::new(*entry.as_netbsd_x8632_acct())
×
3902
        }
3903
        FixedStructType::Fs_Netbsd_x8632_Lastlogx => {
3904
            Box::new(*entry.as_netbsd_x8632_lastlogx())
×
3905
        }
3906
        FixedStructType::Fs_Netbsd_x8632_Utmpx => {
3907
            Box::new(*entry.as_netbsd_x8632_utmpx())
×
3908
        }
3909
        FixedStructType::Fs_Netbsd_x8664_Lastlog => {
3910
            Box::new(*entry.as_netbsd_x8664_lastlog())
×
3911
        }
3912
        FixedStructType::Fs_Netbsd_x8664_Lastlogx => {
3913
            Box::new(*entry.as_netbsd_x8664_lastlogx())
×
3914
        }
3915
        FixedStructType::Fs_Netbsd_x8664_Utmp => {
3916
            Box::new(*entry.as_netbsd_x8664_utmp())
×
3917
        }
3918
        FixedStructType::Fs_Netbsd_x8664_Utmpx => {
3919
            Box::new(*entry.as_netbsd_x8664_utmpx())
×
3920
        }
3921
        FixedStructType::Fs_Openbsd_x86_Lastlog => {
3922
            Box::new(*entry.as_openbsd_x86_lastlog())
×
3923
        }
3924
        FixedStructType::Fs_Openbsd_x86_Utmp => {
3925
            Box::new(*entry.as_openbsd_x86_utmp())
×
3926
        }
3927
    }
3928
}
×
3929

3930
impl Clone for FixedStruct {
3931
    /// Manually implemented `clone`.
3932
    ///
3933
    /// Cannot `#[derive(Clone)]` because that requires
3934
    /// trait `Sized` to be `impl` for all fields of `FixedStruct`.
3935
    /// But the `FixedStructTrait` trait is used as a `dyn` trait
3936
    /// object; it is dynamically sized (it is sized at runtime).
3937
    /// So a `FixedStructTrait` cannot `impl`ement `Sized` thus `FixedStruct` cannot
3938
    /// `impl`ement `Sized` thus must manually implement `clone`.
3939
    fn clone(self: &FixedStruct) -> Self {
×
3940
        defñ!("FixedStruct.clone()");
×
3941
        let fixedstructptr = copy_fixedstructptr(&self.fixedstructptr);
×
3942
        FixedStruct {
×
3943
            fixedstructptr,
×
3944
            fixedstructtype: self.fixedstructtype,
×
3945
            filetypefixedstruct: self.filetypefixedstruct,
×
3946
            fileoffset: self.fileoffset,
×
3947
            dt: self.dt,
×
3948
            tv_pair: self.tv_pair,
×
3949
        }
×
3950
    }
×
3951
}
3952

3953
impl fmt::Debug for FixedStruct
3954
{
3955
    fn fmt(
213,764✔
3956
        &self,
213,764✔
3957
        f: &mut fmt::Formatter,
213,764✔
3958
    ) -> fmt::Result {
213,764✔
3959
        f.debug_struct("FixedStruct")
213,764✔
3960
            .field("size", &self.fixedstructptr.size())
213,764✔
3961
            .field("type", &self.fixedstructtype)
213,764✔
3962
            .field("filetype", &self.filetypefixedstruct)
213,764✔
3963
            .field("fileoffset", &self.fileoffset)
213,764✔
3964
            .field("dt", &self.dt)
213,764✔
3965
            .field("tv_pair", &self.tv_pair)
213,764✔
3966
            .finish()
213,764✔
3967
    }
213,764✔
3968
}
3969

3970
/// Index into a `[u8]` buffer. Used by [`as_bytes`].
3971
///
3972
/// [`as_bytes`]: self::FixedStruct::as_bytes
3973
pub type BufIndex = usize;
3974

3975
/// Information returned from [`as_bytes`].
3976
///
3977
/// Variant `Ok` holds
3978
/// - number of bytes copied
3979
/// - start index of datetime substring
3980
/// - end index of datetime substring
3981
///
3982
/// Variant `Fail` holds number of bytes copied
3983
///
3984
/// [`as_bytes`]: self::FixedStruct::as_bytes
3985
pub enum InfoAsBytes {
3986
    Ok(usize, BufIndex, BufIndex),
3987
    Fail(usize),
3988
}
3989

3990
/// Convert `timeval` types [`tv_sec_type`] and [`tv_usec_type`] to a
3991
/// [`DateTimeL`] instance.
3992
///
3993
/// Allow lossy microsecond conversion.
3994
/// Return `Error` if `tv_sec` conversion fails.
3995
pub fn convert_tvpair_to_datetime(
2,313✔
3996
    tv_pair: tv_pair_type,
2,313✔
3997
    tz_offset: &FixedOffset,
2,313✔
3998
) -> Result<DateTimeL, Error>{
2,313✔
3999
    let tv_usec = tv_pair.1;
2,313✔
4000
    // Firstly, convert i64 to i32 for passing to `timestamp_opt`.
4001
    let mut nsec: nsecs_type = match tv_usec.try_into() {
2,313✔
4002
        Ok(val) => val,
2,311✔
4003
        Err(_err) => {
2✔
4004
            de_wrn!("failed to convert tv_usec 0x{:X} to nsecs_type: {}", tv_usec, _err);
2✔
4005
            // ignore overflow and continue; `tv_usec` merely supplements
4006
            // the more coarse `tv_sec`
4007
            0
2✔
4008
        }
4009
    };
4010
    // Secondly, multiply by 1000 to get nanoseconds.
4011
    nsec = match nsec.checked_mul(1000) {
2,313✔
4012
        Some(val) => val,
2,309✔
4013
        None => {
4014
            de_wrn!("failed to multiply nsec 0x{:X} * 1000: overflow", nsec);
4✔
4015
            // ignore overflow and continue; `tv_usec` merely supplements
4016
            // the more coarse `tv_sec`
4017
            0
4✔
4018
        }
4019
    };
4020

4021
    let tv_sec = tv_pair.0;
2,313✔
4022
    defñ!("{:?}.timestamp({}, {})", tz_offset, tv_sec, nsec);
2,313✔
4023
    match tz_offset.timestamp_opt(
2,313✔
4024
        tv_sec, nsec
2,313✔
4025
    ) {
2,313✔
4026
        LocalResult::None => {
4027
            // try again with zero nanoseconds
4028
            match tz_offset.timestamp_opt(tv_sec, 0) {
2✔
4029
                LocalResult::None => {
4030
                    let err_s = format!(
2✔
4031
                        "failed to convert tv_sec 0x{:08X} to DateTime from tz_offset {}",
2✔
4032
                        tv_sec, tz_offset,
4033
                    );
4034
                    de_wrn!("{}", err_s);
2✔
4035

4036
                    Result::Err(
2✔
4037
                        Error::new(
2✔
4038
                            ErrorKind::InvalidData,
2✔
4039
                            err_s,
2✔
4040
                        )
2✔
4041
                    )
2✔
4042
                }
4043
                LocalResult::Single(dt) => Ok(dt),
×
4044
                LocalResult::Ambiguous(dt, _) => Ok(dt),
×
4045
            }
4046
        }
4047
        LocalResult::Single(dt) => Ok(dt),
2,311✔
4048
        // nothing can disambiguate this so just take the first datetime
4049
        LocalResult::Ambiguous(dt, _) => Ok(dt),
×
4050
    }
4051
}
2,313✔
4052

4053
/// Convert [`DateTimeL`] instance to [`tv_sec_type`] and [`tv_usec_type`].
4054
///
4055
/// Return `Error` if `tv_sec` conversion fails.
4056
pub fn convert_datetime_tvpair(
97✔
4057
    dt: &DateTimeL,
97✔
4058
) -> tv_pair_type {
97✔
4059
    let tv_sec: tv_sec_type = dt.timestamp();
97✔
4060
    let tv_usec: tv_usec_type = dt.timestamp_subsec_micros().into();
97✔
4061

4062
    tv_pair_type(tv_sec, tv_usec)
97✔
4063
}
97✔
4064

4065
#[cfg(any(debug_assertions, test))]
4066
fn struct_field_to_string(buffer: &[u8], offset: usize, sz: usize) -> String {
35,028✔
4067
    let mut s = String::with_capacity(sz);
35,028✔
4068
    for b_ in buffer.iter().skip(offset).take(sz) {
536,635✔
4069
        s.push(byte_to_char_noraw(*b_));
536,635✔
4070
    }
536,635✔
4071

4072
    s
35,028✔
4073
}
35,028✔
4074

4075
/// Helper to [`buffer_to_fixedstructptr`]
4076
/// [`deo!`] for the `$field`
4077
#[cfg(any(debug_assertions, test))]
4078
macro_rules! deo_field_dump {
4079
    ($as_fixedstruct:expr, $field: ident, $buffer: ident) => ({{
4080
        let fs = $as_fixedstruct;
4081

4082
        let base_ptr_offset: usize = std::ptr::addr_of!(*fs) as usize;
4083
        let field_ptr = std::ptr::addr_of!(fs.$field);
4084
        let field_offset = field_ptr as usize - base_ptr_offset;
4085
        let field_sz = std::mem::size_of_val(&fs.$field);
4086
        let field_offset_end = field_offset + field_sz;
4087
        let field_val_string = struct_field_to_string($buffer, field_offset, field_sz);
4088
        let field_name = stringify!($field);
4089

4090
        deo!("{:<20}: {:3}‥{:3} @{:p} | {}",
4091
             field_name, field_offset, field_offset_end, field_ptr, field_val_string);
4092
    }})
4093
}
4094

4095
/// Helper to [`buffer_to_fixedstructptr`]
4096
/// [`deo!`] for the `$field`
4097
#[cfg(any(debug_assertions, test))]
4098
macro_rules! deo_field_dump_num {
4099
    ($as_fixedstruct:expr, $field: ident, $buffer: ident, $typ: ty) => ({{
4100
        let fs = $as_fixedstruct;
4101
        let field_sz = std::mem::size_of_val(&fs.$field);
4102
        deo_field_dump_num_impl!(fs, $field, field_sz, $buffer, $typ);
4103
    }})
4104
}
4105

4106
/// Helper to [`buffer_to_fixedstructptr`]
4107
/// [`deo!`] for the `$field`
4108
///
4109
/// Useful for `packed` structs that cannot be referenced in a macro as
4110
/// `size_of_val!(struct.field)` (like in macro [`deo_field_dump_num`]).
4111
#[cfg(any(debug_assertions, test))]
4112
macro_rules! deo_field_dump_num_szof {
4113
    ($as_fixedstruct:expr, $field: ident, $buffer: ident, $typ: ty) => ({{
4114
        let fs = $as_fixedstruct;
4115
        let field_sz = std::mem::size_of::<$typ>();
4116
        deo_field_dump_num_impl!(fs, $field, field_sz, $buffer, $typ);
4117
    }})
4118
}
4119

4120
/// Helper to [`buffer_to_fixedstructptr`]
4121
/// [`deo!`] for the `$field`
4122
#[cfg(any(debug_assertions, test))]
4123
macro_rules! deo_field_dump_num_impl {
4124
    ($as_fixedstruct:expr, $field: ident, $field_sz: expr, $buffer: ident, $typ: ty) => ({{
4125
        let fs = $as_fixedstruct;
4126

4127
        let base_ptr_offset: usize = std::ptr::addr_of!(*fs) as usize;
4128
        let field_ptr = std::ptr::addr_of!(fs.$field);
4129
        let field_offset = field_ptr as usize - base_ptr_offset;
4130
        let field_offset_end = field_offset + $field_sz;
4131
        let field_val_string = struct_field_to_string($buffer, field_offset, $field_sz);
4132
        let field_name = stringify!($field);
4133
        let value: $typ = fs.$field;
4134

4135
        deo!("{:<20}: {:3}‥{:3} @{:p} | {:<20} 0x{:08X}",
4136
             field_name, field_offset, field_offset_end, field_ptr,
4137
             field_val_string, value);
4138
    }})
4139
}
4140

4141
/// Convert `[u8]` bytes to a [`FixedStructDynPtr`] instance specified by
4142
/// `fixedstructtype`.
4143
///
4144
/// A `buffer` of only null bytes (zero values) will return `None`.
4145
/// A `buffer` of only 0xFF bytes will return `None`.
4146
///
4147
/// unsafe.
4148
pub fn buffer_to_fixedstructptr(buffer: &[u8], fixedstructtype: FixedStructType) -> Option<FixedStructDynPtr>
4,057✔
4149
{
4150
    defn!("(buffer len {:?}, fixedstructtype {:?})", buffer.len(), fixedstructtype);
4,057✔
4151

4152
    let sz: usize = fixedstructtype.size();
4,057✔
4153
    if buffer.len() < sz {
4,057✔
4154
        if cfg!(debug_assertions) && ! cfg!(test)
1✔
4155
        {
4156
            debug_panic!(
×
4157
                "buffer to small; {} bytes but fixedstruct type {:?} is {} bytes",
×
4158
                buffer.len(), fixedstructtype, sz,
×
4159
            );
4160
        }
1✔
4161
        defx!("return None");
1✔
4162
        return None;
1✔
4163
    }
4,056✔
4164
    let slice_ = &buffer[..sz];
4,056✔
4165
    // check for all zero bytes
4166
    if slice_.iter().all(|&x| x == 0) {
65,459✔
4167
        defx!("buffer[0‥{}] is all 0x00 bytes; return None", slice_.len());
1,038✔
4168
        return None;
1,038✔
4169
    }
3,018✔
4170
    // check for all 0xFF bytes
4171
    if slice_.iter().all(|&x| x == 0xFF) {
8,700✔
4172
        defx!("buffer[0‥{}] is all 0xFF bytes; return None", slice_.len());
78✔
4173
        return None;
78✔
4174
    }
2,940✔
4175
    #[cfg(debug_assertions)]
4176
    {
4177
        // print buffer bytes to the console
4178
        const LEN: usize = 16;
4179
        defo!("\nbuffer[‥{}] ({} bytes per line)\n[", sz, LEN);
2,940✔
4180
        let _lock = si_trace_print::printers::GLOBAL_LOCK_PRINTER.lock().unwrap();
2,940✔
4181
        for (i, b_) in slice_.iter().enumerate().take(sz) {
547,560✔
4182
            eprint!("{:?}, ", *b_ as char);
547,560✔
4183
            if i != 0 && i % LEN == 0 {
547,560✔
4184
                eprintln!();
31,301✔
4185
            }
516,259✔
4186
        }
4187
        eprintln!("\n]");
2,940✔
4188
        for (i, b_) in slice_.iter().enumerate().take(sz) {
547,560✔
4189
            eprint!("{}", byte_to_char_noraw(*b_));
547,560✔
4190
            if i != 0 && i % LEN == 0 {
547,560✔
4191
                eprintln!();
31,301✔
4192
            }
516,259✔
4193
        }
4194
        eprintln!();
2,940✔
4195
    }
4196
    let entry: FixedStructDynPtr = match fixedstructtype {
2,940✔
4197
        FixedStructType::Fs_Freebsd_x8664_Utmpx => {
4198
            unsafe {
4✔
4199
                Box::new(
4✔
4200
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<freebsd_x8664::utmpx>())
4✔
4201
                )
4✔
4202
            }
4✔
4203
        }
4204
        FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => {
4205
            unsafe {
4206
                Box::new(
3✔
4207
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<linux_arm64aarch64::lastlog>())
3✔
4208
                )
3✔
4209
            }
4210
        }
4211
        FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => {
4212
            unsafe {
4213
                Box::new(
3✔
4214
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<linux_arm64aarch64::utmpx>())
3✔
4215
                )
3✔
4216
            }
4217
        }
4218
        FixedStructType::Fs_Linux_x86_Acct => {
4219
            unsafe {
4220
                Box::new(
583✔
4221
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<linux_x86::acct>())
583✔
4222
                )
583✔
4223
            }
4224
        }
4225
        FixedStructType::Fs_Linux_x86_Acct_v3 => {
4226
            unsafe {
4227
                Box::new(
583✔
4228
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<linux_x86::acct_v3>())
583✔
4229
                )
583✔
4230
            }
4231
        }
4232
        FixedStructType::Fs_Linux_x86_Lastlog => {
4233
            unsafe {
4234
                Box::new(
10✔
4235
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<linux_x86::lastlog>())
10✔
4236
                )
10✔
4237
            }
4238
        }
4239
        FixedStructType::Fs_Linux_x86_Utmpx => {
4240
            unsafe {
4241
                Box::new(
1,147✔
4242
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<linux_x86::utmpx>())
1,147✔
4243
                )
1,147✔
4244
            }
4245
        }
4246
        FixedStructType::Fs_Netbsd_x8632_Acct => {
4247
            unsafe {
4248
                Box::new(
3✔
4249
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<netbsd_x8632::acct>())
3✔
4250
                )
3✔
4251
            }
4252
        }
4253
        FixedStructType::Fs_Netbsd_x8632_Lastlogx => {
4254
            unsafe {
4255
                Box::new(
3✔
4256
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<netbsd_x8632::lastlogx>())
3✔
4257
                )
3✔
4258
            }
4259
        }
4260
        FixedStructType::Fs_Netbsd_x8632_Utmpx => {
4261
            unsafe {
4262
                Box::new(
3✔
4263
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<netbsd_x8632::utmpx>())
3✔
4264
                )
3✔
4265
            }
4266
        }
4267
        FixedStructType::Fs_Netbsd_x8664_Lastlog => {
4268
            unsafe {
4269
                Box::new(
583✔
4270
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<netbsd_x8664::lastlog>())
583✔
4271
                )
583✔
4272
            }
4273
        }
4274
        FixedStructType::Fs_Netbsd_x8664_Lastlogx => {
4275
            unsafe {
4276
                Box::new(
3✔
4277
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<netbsd_x8664::lastlogx>())
3✔
4278
                )
3✔
4279
            }
4280
        }
4281
        FixedStructType::Fs_Netbsd_x8664_Utmp => {
4282
            unsafe {
4283
                Box::new(
3✔
4284
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<netbsd_x8664::utmp>())
3✔
4285
                )
3✔
4286
            }
4287
        }
4288
        FixedStructType::Fs_Netbsd_x8664_Utmpx => {
4289
            unsafe {
4290
                Box::new(
3✔
4291
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<netbsd_x8664::utmpx>())
3✔
4292
                )
3✔
4293
            }
4294
        }
4295
        FixedStructType::Fs_Openbsd_x86_Lastlog => {
4296
            unsafe {
4297
                Box::new(
3✔
4298
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<openbsd_x86::lastlog>())
3✔
4299
                )
3✔
4300
            }
4301
        }
4302
        FixedStructType::Fs_Openbsd_x86_Utmp => {
4303
            unsafe {
4304
                Box::new(
3✔
4305
                    std::ptr::read_unaligned(slice_.as_ptr().cast::<openbsd_x86::utmp>())
3✔
4306
                )
3✔
4307
            }
4308
        }
4309
    };
4310

4311
    #[cfg(any(debug_assertions, test))]
4312
    match fixedstructtype {
2,940✔
4313
        // print struct member offsets and bytes
4314
        // `addr_of!` used here due to unaligned references being a warning:
4315
        // credit https://stackoverflow.com/a/26271748/471376
4316
        FixedStructType::Fs_Freebsd_x8664_Utmpx => {
4✔
4317
            let utmpx: &freebsd_x8664::utmpx = entry.as_freebsd_x8664_utmpx();
4✔
4318

4✔
4319
            deo!("freebsd_x8664::utmpx offsets and bytes, size {}", utmpx.size());
4✔
4320
            deo_field_dump_num!(utmpx, ut_type, buffer, freebsd_x8664::c_short);
4✔
4321
            deo_field_dump!(utmpx, ut_tv, buffer);
4✔
4322
            deo_field_dump!(utmpx, ut_id, buffer);
4✔
4323
            deo_field_dump_num!(utmpx, ut_pid, buffer, freebsd_x8664::pid_t);
4✔
4324
            deo_field_dump!(utmpx, ut_user, buffer);
4✔
4325
            deo_field_dump!(utmpx, ut_line, buffer);
4✔
4326
            deo_field_dump!(utmpx, ut_host, buffer);
4✔
4327
            deo_field_dump!(utmpx, __ut_spare, buffer);
4✔
4328
        }
4✔
4329
        FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => {
3✔
4330
            let lastlog: &linux_arm64aarch64::lastlog = entry.as_linux_arm64aarch64_lastlog();
3✔
4331

3✔
4332
            deo!("linux_arm64aarch64::lastlog offsets and bytes, size {}", lastlog.size());
3✔
4333
            deo_field_dump_num!(lastlog, ll_time, buffer, linux_arm64aarch64::ll_time_t);
3✔
4334
            deo_field_dump!(lastlog, ll_line, buffer);
3✔
4335
            deo_field_dump!(lastlog, ll_host, buffer);
3✔
4336
        }
3✔
4337
        FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => {
3✔
4338
            let utmpx: &linux_arm64aarch64::utmpx = entry.as_linux_arm64aarch64_utmpx();
3✔
4339

3✔
4340
            deo!("linux_arm64aarch64::utmpx offsets and bytes, size {}", utmpx.size());
3✔
4341
            deo_field_dump_num!(utmpx, ut_type, buffer, linux_arm64aarch64::c_short);
3✔
4342
            deo_field_dump_num!(utmpx, ut_pid, buffer, linux_arm64aarch64::pid_t);
3✔
4343
            deo_field_dump!(utmpx, ut_line, buffer);
3✔
4344
            deo_field_dump!(utmpx, ut_id, buffer);
3✔
4345
            deo_field_dump!(utmpx, ut_user, buffer);
3✔
4346
            deo_field_dump!(utmpx, ut_host, buffer);
3✔
4347
            deo_field_dump_num!(utmpx, ut_exit, buffer, i32);
3✔
4348
            deo_field_dump_num!(utmpx, ut_session, buffer, i64);
3✔
4349
            deo_field_dump!(utmpx, ut_tv, buffer);
3✔
4350
            deo_field_dump!(utmpx, ut_addr_v6, buffer);
3✔
4351
            deo_field_dump!(utmpx, __glibc_reserved, buffer);
3✔
4352
        }
3✔
4353
        FixedStructType::Fs_Linux_x86_Acct => {
583✔
4354
            let acct: &linux_x86::acct = entry.as_linux_x86_acct();
583✔
4355

583✔
4356
            deo!("linux_x86::acct offsets and bytes, size {}", acct.size());
583✔
4357
            deo_field_dump_num!(acct, ac_flag, buffer, linux_x86::c_char);
583✔
4358
            deo_field_dump_num!(acct, ac_uid, buffer, u16);
583✔
4359
            deo_field_dump_num!(acct, ac_gid, buffer, u16);
583✔
4360
            deo_field_dump_num!(acct, ac_tty, buffer, u16);
583✔
4361
            deo_field_dump_num!(acct, ac_btime, buffer, linux_x86::b_time_t);
583✔
4362
            deo_field_dump_num!(acct, ac_utime, buffer, linux_x86::comp_t);
583✔
4363
            deo_field_dump_num!(acct, ac_stime, buffer, linux_x86::comp_t);
583✔
4364
            deo_field_dump_num!(acct, ac_etime, buffer, linux_x86::comp_t);
583✔
4365
            deo_field_dump_num!(acct, ac_mem, buffer, linux_x86::comp_t);
583✔
4366
            deo_field_dump_num!(acct, ac_io, buffer, linux_x86::comp_t);
583✔
4367
            deo_field_dump_num!(acct, ac_rw, buffer, linux_x86::comp_t);
583✔
4368
            deo_field_dump_num!(acct, ac_minflt, buffer, linux_x86::comp_t);
583✔
4369
            deo_field_dump_num!(acct, ac_majflt, buffer, linux_x86::comp_t);
583✔
4370
            deo_field_dump_num!(acct, ac_swaps, buffer, linux_x86::comp_t);
583✔
4371
            deo_field_dump_num!(acct, ac_exitcode, buffer, u32);
583✔
4372
            deo_field_dump!(acct, ac_comm, buffer);
583✔
4373
        }
583✔
4374
        FixedStructType::Fs_Linux_x86_Acct_v3 => {
583✔
4375
            let acct: &linux_x86::acct_v3 = entry.as_linux_x86_acct_v3();
583✔
4376

583✔
4377
            deo!("linux_x86::acct_v3 offsets and bytes, size {}", acct.size());
583✔
4378
            deo_field_dump_num!(acct, ac_flag, buffer, linux_x86::c_char);
583✔
4379
            deo_field_dump_num!(acct, ac_version, buffer, linux_x86::c_char);
583✔
4380
            deo_field_dump_num!(acct, ac_tty, buffer, u16);
583✔
4381
            deo_field_dump_num!(acct, ac_exitcode, buffer, u32);
583✔
4382
            deo_field_dump_num!(acct, ac_uid, buffer, u32);
583✔
4383
            deo_field_dump_num!(acct, ac_gid, buffer, u32);
583✔
4384
            deo_field_dump_num!(acct, ac_pid, buffer, u32);
583✔
4385
            deo_field_dump_num!(acct, ac_ppid, buffer, u32);
583✔
4386
            deo_field_dump_num!(acct, ac_btime, buffer, linux_x86::b_time_t);
583✔
4387
            deo_field_dump!(acct, ac_etime, buffer);
583✔
4388
            deo_field_dump_num!(acct, ac_utime, buffer, linux_x86::comp_t);
583✔
4389
            deo_field_dump_num!(acct, ac_stime, buffer, linux_x86::comp_t);
583✔
4390
            deo_field_dump_num!(acct, ac_mem, buffer, linux_x86::comp_t);
583✔
4391
            deo_field_dump_num!(acct, ac_io, buffer, linux_x86::comp_t);
583✔
4392
            deo_field_dump_num!(acct, ac_rw, buffer, linux_x86::comp_t);
583✔
4393
            deo_field_dump_num!(acct, ac_minflt, buffer, linux_x86::comp_t);
583✔
4394
            deo_field_dump_num!(acct, ac_majflt, buffer, linux_x86::comp_t);
583✔
4395
            deo_field_dump_num!(acct, ac_swaps, buffer, linux_x86::comp_t);
583✔
4396
            deo_field_dump!(acct, ac_comm, buffer);
583✔
4397
        }
583✔
4398
        FixedStructType::Fs_Linux_x86_Lastlog => {
10✔
4399
            let lastlog: &linux_x86::lastlog = entry.as_linux_x86_lastlog();
10✔
4400

10✔
4401
            deo!("linux_x86::lastlog offsets and bytes, size {}", lastlog.size());
10✔
4402
            deo_field_dump_num!(lastlog, ll_time, buffer, linux_x86::ll_time_t);
10✔
4403
            deo_field_dump!(lastlog, ll_line, buffer);
10✔
4404
            deo_field_dump!(lastlog, ll_host, buffer);
10✔
4405
        }
10✔
4406
        FixedStructType::Fs_Linux_x86_Utmpx => {
1,147✔
4407
            let utmpx: &linux_x86::utmpx = entry.as_linux_x86_utmpx();
1,147✔
4408

1,147✔
4409
            deo!("linux_x86::utmpx offsets and bytes, size {}", utmpx.size());
1,147✔
4410
            deo_field_dump_num!(utmpx, ut_type, buffer, linux_x86::c_short);
1,147✔
4411
            deo_field_dump_num!(utmpx, ut_pid, buffer, linux_x86::pid_t);
1,147✔
4412
            deo_field_dump!(utmpx, ut_line, buffer);
1,147✔
4413
            deo_field_dump!(utmpx, ut_id, buffer);
1,147✔
4414
            deo_field_dump!(utmpx, ut_user, buffer);
1,147✔
4415
            deo_field_dump!(utmpx, ut_host, buffer);
1,147✔
4416
            deo_field_dump!(utmpx, ut_exit, buffer);
1,147✔
4417
            deo_field_dump_num!(utmpx, ut_session, buffer, i32);
1,147✔
4418
            deo_field_dump!(utmpx, ut_tv, buffer);
1,147✔
4419
            deo_field_dump!(utmpx, ut_addr_v6, buffer);
1,147✔
4420
            deo_field_dump!(utmpx, __glibc_reserved, buffer);
1,147✔
4421
        }
1,147✔
4422
        FixedStructType::Fs_Netbsd_x8632_Acct => {
3✔
4423
            let acct: &netbsd_x8632::acct = entry.as_netbsd_x8632_acct();
3✔
4424

3✔
4425
            deo!("netbsd_x8664::acct offsets and bytes, size {}", acct.size());
3✔
4426
            deo_field_dump!(acct, ac_comm, buffer);
3✔
4427
            deo_field_dump_num_szof!(acct, ac_utime, buffer, netbsd_x8632::comp_t);
3✔
4428
            deo_field_dump_num_szof!(acct, ac_stime, buffer, netbsd_x8632::comp_t);
3✔
4429
            deo_field_dump_num_szof!(acct, ac_etime, buffer, netbsd_x8632::comp_t);
3✔
4430
            deo_field_dump_num_szof!(acct, ac_btime, buffer, netbsd_x8632::time_t);
3✔
4431
            deo_field_dump_num_szof!(acct, ac_uid, buffer, netbsd_x8632::uid_t);
3✔
4432
            deo_field_dump_num_szof!(acct, ac_gid, buffer, netbsd_x8632::gid_t);
3✔
4433
            deo_field_dump_num_szof!(acct, ac_mem, buffer, netbsd_x8632::comp_t);
3✔
4434
            deo_field_dump_num_szof!(acct, ac_io, buffer, netbsd_x8632::comp_t);
3✔
4435
            deo_field_dump_num_szof!(acct, ac_tty, buffer, netbsd_x8632::dev_t);
3✔
4436
            deo_field_dump_num_szof!(acct, ac_flag, buffer, netbsd_x8632::uint8_t);
3✔
4437
        }
3✔
4438
        FixedStructType::Fs_Netbsd_x8632_Lastlogx => {
3✔
4439
            let lastlogx: &netbsd_x8632::lastlogx = entry.as_netbsd_x8632_lastlogx();
3✔
4440

3✔
4441
            deo!("netbsd_x8632::lastlogx offsets and bytes, size {}", lastlogx.size());
3✔
4442
            deo_field_dump!(lastlogx, ll_tv, buffer);
3✔
4443
            deo_field_dump!(lastlogx, ll_line, buffer);
3✔
4444
            deo_field_dump!(lastlogx, ll_host, buffer);
3✔
4445
            deo_field_dump!(lastlogx, ll_ss, buffer);
3✔
4446
        }
3✔
4447
        FixedStructType::Fs_Netbsd_x8632_Utmpx => {
3✔
4448
            let utmpx: &netbsd_x8632::utmpx = entry.as_netbsd_x8632_utmpx();
3✔
4449

3✔
4450
            deo!("netbsd_x8632::utmpx offsets and bytes, size {}", utmpx.size());
3✔
4451
            deo_field_dump!(utmpx, ut_name, buffer);
3✔
4452
            deo_field_dump!(utmpx, ut_id, buffer);
3✔
4453
            deo_field_dump!(utmpx, ut_line, buffer);
3✔
4454
            deo_field_dump!(utmpx, ut_host, buffer);
3✔
4455
            deo_field_dump_num!(utmpx, ut_session, buffer, netbsd_x8632::uint16_t);
3✔
4456
            deo_field_dump_num!(utmpx, ut_type, buffer, netbsd_x8632::uint16_t);
3✔
4457
            deo_field_dump_num!(utmpx, ut_pid, buffer, netbsd_x8632::pid_t);
3✔
4458
            deo_field_dump!(utmpx, ut_exit, buffer);
3✔
4459
            deo_field_dump!(utmpx, ut_ss, buffer);
3✔
4460
            deo_field_dump!(utmpx, ut_tv, buffer);
3✔
4461
            deo_field_dump!(utmpx, ut_pad, buffer);
3✔
4462
        }
3✔
4463
        FixedStructType::Fs_Netbsd_x8664_Lastlog => {
583✔
4464
            let lastlog: &netbsd_x8664::lastlog = entry.as_netbsd_x8664_lastlog();
583✔
4465

583✔
4466
            deo!("netbsd_x8664::lastlog offsets and bytes, size {}", lastlog.size());
583✔
4467
            deo_field_dump_num!(lastlog, ll_time, buffer, netbsd_x8664::time_t);
583✔
4468
            deo_field_dump!(lastlog, ll_line, buffer);
583✔
4469
            deo_field_dump!(lastlog, ll_host, buffer);
583✔
4470
        }
583✔
4471
        FixedStructType::Fs_Netbsd_x8664_Lastlogx => {
3✔
4472
            let lastlogx: &netbsd_x8664::lastlogx = entry.as_netbsd_x8664_lastlogx();
3✔
4473

3✔
4474
            deo!("netbsd_x8664::lastlogx offsets and bytes, size {}", lastlogx.size());
3✔
4475
            deo_field_dump!(lastlogx, ll_tv, buffer);
3✔
4476
            deo_field_dump!(lastlogx, ll_line, buffer);
3✔
4477
            deo_field_dump!(lastlogx, ll_host, buffer);
3✔
4478
            deo_field_dump!(lastlogx, ll_ss, buffer);
3✔
4479
        }
3✔
4480
        FixedStructType::Fs_Netbsd_x8664_Utmp => {
3✔
4481
            let utmp: &netbsd_x8664::utmp = entry.as_netbsd_x8664_utmp();
3✔
4482

3✔
4483
            deo!("netbsd_x8664::utmp offsets and bytes, size {}", utmp.size());
3✔
4484
            deo_field_dump!(utmp, ut_line, buffer);
3✔
4485
            deo_field_dump!(utmp, ut_name, buffer);
3✔
4486
            deo_field_dump!(utmp, ut_host, buffer);
3✔
4487
            deo_field_dump_num!(utmp, ut_time, buffer, netbsd_x8664::time_t);
3✔
4488
        }
3✔
4489
        FixedStructType::Fs_Netbsd_x8664_Utmpx => {
3✔
4490
            let utmpx: &netbsd_x8664::utmpx = entry.as_netbsd_x8664_utmpx();
3✔
4491

3✔
4492
            deo!("netbsd_x8664::utmpx offsets and bytes, size {}", utmpx.size());
3✔
4493
            deo_field_dump!(utmpx, ut_user, buffer);
3✔
4494
            deo_field_dump!(utmpx, ut_id, buffer);
3✔
4495
            deo_field_dump!(utmpx, ut_line, buffer);
3✔
4496
            deo_field_dump!(utmpx, ut_host, buffer);
3✔
4497
            deo_field_dump_num!(utmpx, ut_session, buffer, netbsd_x8664::uint16_t);
3✔
4498
            deo_field_dump_num!(utmpx, ut_type, buffer, netbsd_x8664::uint16_t);
3✔
4499
            deo_field_dump_num!(utmpx, ut_pid, buffer, netbsd_x8664::pid_t);
3✔
4500
            deo_field_dump!(utmpx, ut_exit, buffer);
3✔
4501
            deo_field_dump!(utmpx, ut_tv, buffer);
3✔
4502
            deo_field_dump!(utmpx, ut_pad, buffer);
3✔
4503
        }
3✔
4504
        FixedStructType::Fs_Openbsd_x86_Lastlog => {
3✔
4505
            let lastlog: &openbsd_x86::lastlog = entry.as_openbsd_x86_lastlog();
3✔
4506

3✔
4507
            deo!("openbsd_x86::lastlog offsets and bytes, size {}", lastlog.size());
3✔
4508
            deo_field_dump_num!(lastlog, ll_time, buffer, openbsd_x86::time_t);
3✔
4509
            deo_field_dump!(lastlog, ll_line, buffer);
3✔
4510
            deo_field_dump!(lastlog, ll_host, buffer);
3✔
4511
        }
3✔
4512
        FixedStructType::Fs_Openbsd_x86_Utmp => {
3✔
4513
            let utmp: &openbsd_x86::utmp = entry.as_openbsd_x86_utmp();
3✔
4514

3✔
4515
            deo!("openbsd_x86::utmp offsets and bytes, size {}", utmp.size());
3✔
4516
            deo_field_dump!(utmp, ut_line, buffer);
3✔
4517
            deo_field_dump!(utmp, ut_name, buffer);
3✔
4518
            deo_field_dump!(utmp, ut_host, buffer);
3✔
4519
            deo_field_dump_num!(utmp, ut_time, buffer, openbsd_x86::time_t);
3✔
4520
        }
3✔
4521
    }
4522
    defx!("return entry with fixedstruct_type {:?}",
2,940✔
4523
          entry.fixedstruct_type());
2,940✔
4524

4525
    Some(entry)
2,940✔
4526
}
4,057✔
4527

4528
/// Helper to [`FixedStruct::as_bytes`].
4529
/// Write a byte `b` that is `u8` to the `buffer` at index `at`
4530
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4531
macro_rules! set_buffer_at_or_err_u8 {
4532
    ($buffer:ident, $at:ident, $b:expr) => ({{
4533
        if $at >= $buffer.len() {
4534
            return InfoAsBytes::Fail($at);
4535
        }
4536
        $buffer[$at] = $b;
4537
        $at += 1;
4538
    }})
4539
}
4540

4541
/// Helper to [`FixedStruct::as_bytes`].
4542
/// Write a byte `b` that is `i8` to the `buffer` at index `at`
4543
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4544
macro_rules! set_buffer_at_or_err_i8 {
4545
    ($buffer:ident, $at:ident, $c:expr) => ({{
4546
        let c_: u8 = match ($c).try_into() {
4547
            Ok(val) => val,
4548
            Err(_) => 0,
4549
        };
4550
        set_buffer_at_or_err_u8!($buffer, $at, c_);
4551
    }})
4552
}
4553

4554
/// Helper to [`FixedStruct::as_bytes`].
4555
/// Write a byte `b` that is `&[u8]` to the `buffer` at index `at`
4556
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4557
macro_rules! set_buffer_at_or_err_u8_array {
4558
    ($buffer:ident, $at:ident, $b:expr) => ({{
4559
        for b_ in $b.iter() {
4560
            set_buffer_at_or_err_u8!($buffer, $at, *b_);
4561
        }
4562
    }})
4563
}
4564

4565
/// Helper to [`FixedStruct::as_bytes`].
4566
/// Write a `str_` to the `buffer` starting `at` the given index.
4567
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4568
macro_rules! set_buffer_at_or_err_str {
4569
    ($buffer:ident, $at:ident, $str_:expr) => ({{
4570
        for b_ in $str_.bytes() {
4571
            set_buffer_at_or_err_u8!($buffer, $at, b_);
4572
        }
4573
    }})
4574
}
4575

4576
/// Helper to [`FixedStruct::as_bytes`].
4577
/// Write a `string_` to the `buffer` starting `at` the given index.
4578
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4579
macro_rules! set_buffer_at_or_err_string {
4580
    ($buffer:ident, $at:ident, $string_:expr) => ({{
4581
        for b_ in $string_.as_bytes() {
4582
            set_buffer_at_or_err_u8!($buffer, $at, *b_);
4583
        }
4584
    }})
4585
}
4586

4587
/// Helper to [`FixedStruct::as_bytes`].
4588
/// Write a `cstr` that may be missing ending '\0' to the `buffer` starting at
4589
/// the given index `at` up to `cstr_len` bytes.
4590
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4591
macro_rules! set_buffer_at_or_err_cstrn {
4592
    ($buffer:ident, $at:ident, $cstr:expr) => ({{
4593
        let cstr_sz = std::mem::size_of_val(& $cstr);
4594
        for (i, b_) in $cstr.iter().enumerate() {
4595
            if b_ == &0 || i == cstr_sz {
4596
                break;
4597
            }
4598
            set_buffer_at_or_err_i8!($buffer, $at, *b_);
4599
        }
4600
    }})
4601
}
4602

4603
/// Helper to [`FixedStruct::as_bytes`].
4604
/// Write the `ut_type` that is `i16` to the `buffer` at index`at`.
4605
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4606
macro_rules! set_buffer_at_or_err_ut_type {
4607
    ($buffer:ident, $at:ident, $ut_type:expr, $type_:ty, $len:ident) => ({{
4608
        #[allow(non_camel_case_types)]
4609
        {
4610
            // sanity check passed number type is 2 bytes or less so `buffer_num` is enough
4611
            assertcp!(std::mem::size_of::<$type_>() <= 2);
4612
        }
4613
        let mut buffer_num = [0u8; 8];
4614
        match &$ut_type {
4615
            n if &0 <= n && n < &$len => {
4616
                set_buffer_at_or_err_str!($buffer, $at, UT_TYPE_VAL_TO_STR[*n as usize]);
4617
            }
4618
            n_ => {
4619
                let num = n_.numtoa(10, &mut buffer_num);
4620
                set_buffer_at_or_err_u8_array!($buffer, $at, num);
4621
            },
4622
        }
4623
    }})
4624
}
4625

4626
/// Helper to [`FixedStruct::as_bytes`].
4627
/// Write the `ut_type` that is `i16` to the `buffer` at index`at`.
4628
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4629
macro_rules! set_buffer_at_or_err_ut_type_i16 {
4630
    ($buffer:ident, $at:ident, $ut_type:expr) => ({{
4631
        set_buffer_at_or_err_ut_type!($buffer, $at, $ut_type, i16, UT_TYPE_VAL_TO_STR_LEN_i16)
4632
    }})
4633
}
4634

4635
/// Helper to [`FixedStruct::as_bytes`].
4636
/// Write the `ut_type` that is `u16` to the `buffer` at index `at`.
4637
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4638
macro_rules! set_buffer_at_or_err_ut_type_u16 {
4639
    ($buffer:ident, $at:ident, $ut_type:expr) => ({{
4640
        set_buffer_at_or_err_ut_type!($buffer, $at, $ut_type, u16, UT_TYPE_VAL_TO_STR_LEN_u16)
4641
    }})
4642
}
4643

4644
/// Helper to [`FixedStruct::as_bytes`].
4645
/// Write the `number` value of type `$type_` into `buffer` at index `at`.
4646
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4647
macro_rules! set_buffer_at_or_err_number {
4648
    ($buffer:ident, $at:ident, $number:expr, $type_:ty) => ({{
4649
        #[allow(non_camel_case_types)]
4650
        {
4651
            // sanity check passed number type is 8 bytes or less so `buffer_num` is enough
4652
            assertcp!(std::mem::size_of::<$type_>() <= 8);
4653
        }
4654
        let mut buffer_num = [0u8; 22];
4655
        // XXX: copy to local variable to avoid packed warning
4656
        let num_val = $number;
4657
        let num = num_val.numtoa(10, &mut buffer_num);
4658
        set_buffer_at_or_err_u8_array!($buffer, $at, num);
4659
    }})
4660
}
4661

4662
/// Helper to [`FixedStruct::as_bytes`].
4663
/// Write the `number` value of type `i64` into `buffer` at index `at`.
4664
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4665
macro_rules! set_buffer_at_or_err_number_f32 {
4666
    ($buffer:ident, $at:ident, $number:expr, $type_:ty) => ({{
4667
        // XXX: copy to local variable to avoid packed warning
4668
        let num = $number;
4669
        let number_string = format!("{}", num);
4670
        set_buffer_at_or_err_string!($buffer, $at, number_string);
4671
    }})
4672
}
4673

4674
/// Helper to [`FixedStruct::as_bytes`].
4675
/// Write the `number` value of type `i64` into `buffer` at index `at`.
4676
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4677
macro_rules! set_buffer_at_or_err_number_bin4 {
4678
    ($buffer:ident, $at:ident, $number:expr, $type_:ty) => ({{
4679
        let number_string = format!("0b{:04b}", $number);
4680
        set_buffer_at_or_err_string!($buffer, $at, number_string);
4681
    }})
4682
}
4683

4684
/// Helper to [`FixedStruct::as_bytes`].
4685
/// Write the `number`that is an IPv4 address into `buffer` at index `at`.
4686
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4687
macro_rules! set_buffer_at_or_err_ipv4 {
4688
    ($buffer:ident, $at:ident, $value:expr) => ({{
4689
        // separate each octet of the IPv4 address
4690
        let o0: u8 = (($value >> 24) & 0xFF) as u8;
4691
        let o1: u8 = (($value >> 16) & 0xFF) as u8;
4692
        let o2: u8 = (($value >> 8) & 0xFF) as u8;
4693
        let o3: u8 = ($value & 0xFF) as u8;
4694
        // write each octet to the buffer
4695
        for (i, b_) in (&[o3, o2, o1, o0]).iter().enumerate() {
4696
            set_buffer_at_or_err_number!($buffer, $at, *b_, u8);
4697
            if i != 3 {
4698
                set_buffer_at_or_err_u8!($buffer, $at, b'.');
4699
            }
4700
        }
4701
    }})
4702
}
4703

4704
/// Helper to [`FixedStruct::as_bytes`].
4705
/// Write the `number`that is an IPv6 address into `buffer` at index `at`.
4706
/// If the index is out of bounds, return `InfoAsBytes::Fail`.
4707
macro_rules! set_buffer_at_or_err_ipv6 {
4708
    ($buffer:ident, $at:ident, $value:expr) => ({{
4709
        for b_ in format!("{:X}:{:X}:{:X}:{:X}",
4710
            &$value[0],
4711
            &$value[1],
4712
            &$value[2],
4713
            &$value[3],
4714
        ).as_str().bytes() {
4715
            set_buffer_at_or_err_u8!($buffer, $at, b_);
4716
        }
4717
    }})
4718
}
4719

4720
/// Helper to [`FixedStruct::from_fixedstructptr`]
4721
macro_rules! tv_or_err_tv_sec {
4722
    ($fixedstructptr: ident, $tv_sec: expr) => ({{
4723
        match $tv_sec.try_into() {
4724
            Ok(val) => val,
4725
            Err(err) => {
4726
                let err_str = format!(
4727
                    "{} failed to convert tv_sec {:?}; {}",
4728
                    stringify!($tv_sec), $tv_sec, err
4729
                );
4730
                de_err!("{}", err_str);
4731
                defx!("return Err {}", err);
4732
                return Result::Err(
4733
                    Error::new(ErrorKind::InvalidData, err_str)
4734
                );
4735
            }
4736
        }
4737
    }})
4738
}
4739

4740
/// Helper to [`FixedStruct::from_fixedstructptr`]
4741
macro_rules! tv_to_datetime_or_err {
4742
    ($tv_sec: ident, $tv_usec: ident, $tz_offset: ident) => ({{
4743
        match convert_tvpair_to_datetime(tv_pair_type($tv_sec, $tv_usec), $tz_offset) {
4744
            Ok(dt) => dt,
4745
            Err(err) => {
4746
                // `convert_tvpair_to_datetime` should have already debug printed an error
4747
                // so don't `de_err!` here
4748
                defx!("return Err {}", err);
4749
                return Result::Err(err);
4750
            }
4751
        }
4752
    }})
4753
}
4754

4755
/// Helper to [`FixedStruct::score_fixedstruct`]
4756
/// Increase score if the buffer appears to be a valid C string (has
4757
/// typical ASCII characters found in such strings).
4758
macro_rules! score_fixedstruct_cstr {
4759
    ($score:ident, $cstr:expr) => {{
4760
        let cstr_: &CStr = $cstr;
4761
        if !cstr_.is_empty() {
4762
            $score += 1;
4763
            for c in cstr_.to_bytes().iter() {
4764
                match c {
4765
                    // all visible ASCII characters <128
4766
                    &(b' '..=b'~') => $score += 2,
4767
                    // 0xFF is very likely bad data
4768
                    0xFF => $score -= 5,
4769
                    _ => $score -= 3,
4770
                }
4771
            }
4772
        }
4773
        defo!(
4774
            "score_fixedstruct_cstr ({}): score={}",
4775
            stringify!($cstr), $score
4776
        );
4777
    }};
4778
}
4779

4780
/// Helper to [`FixedStruct::score_fixedstruct`]
4781
/// Decrease score if bytes after the first null byte are not null.
4782
/// Non-null bytes after the first null byte mean the field is not a C string.
4783
macro_rules! score_fixedstruct_cstr_no_data_after_null {
4784
    ($score:ident, $buffer:expr) => {{
4785
        let mut found_null: bool = false;
4786
        for b in $buffer.iter() {
4787
            if *b == 0 {
4788
                found_null = true;
4789
                continue;
4790
            }
4791
            if !found_null {
4792
                continue;
4793
            }
4794
            match b {
4795
                // there is a non-null byte after the prior null bytes
4796
                _ if *b != 0 => $score -= 5,
4797
                _ => {}
4798
            }
4799
        }
4800
        defo!(
4801
            "score_fixedstruct_cstr_no_data_after_null ({}): score={}",
4802
            stringify!($buffer), $score
4803
        );
4804
    }};
4805
}
4806

4807
/// Helper to [`FixedStruct::score_fixedstruct`]
4808
/// Increase score if the last byte of the buffer is null.
4809
/// Decrease score if the last byte of the buffer is not null.
4810
macro_rules! score_fixedstruct_cstr_null_terminator {
4811
    ($score:ident, $buffer:expr) => {{
4812
        if let Some(b) = $buffer.iter().nth($buffer.len() - 1) {
4813
            if *b == 0 {
4814
                $score += 10;
4815
            } else {
4816
                $score -= 10;
4817
            }
4818
        }
4819
        defo!(
4820
            "score_fixedstruct_cstr_null_terminator ({}): score={}",
4821
            stringify!($buffer), $score
4822
        );
4823
    }};
4824
}
4825

4826
/// Helper to [`FixedStruct::score_fixedstruct`]
4827
/// Increase score if all bytes are null.
4828
/// Decrease score if any bytes are not null.
4829
macro_rules! score_fixedstruct_buffer_all_null {
4830
    ($score:ident, $buffer:expr) => {{
4831
        let mut all_zero: bool = true;
4832
        if let Some(b) = $buffer.iter().nth($buffer.len() - 1) {
4833
            if *b != 0 {
4834
                $score -= 4;
4835
                all_zero = false;
4836
            }
4837
        }
4838
        if all_zero && $buffer.len() > 0 {
4839
            $score += 10;
4840
        }
4841
        defo!(
4842
            "score_fixedstruct_buffer_all_null ({}): score={}",
4843
            stringify!($buffer), $score
4844
        );
4845
    }};
4846
}
4847

4848
/// Helper to [`FixedStruct::score_fixedstruct`]
4849
/// Increase score if the value is not zero.
4850
/// Decrease score if the value is zero.
4851
macro_rules! score_fixedstruct_value_not_zero {
4852
    ($score:ident, $value:expr) => {{
4853
        if $value != 0 {
4854
            $score += 10;
4855
        } else {
4856
            $score -= 10;
4857
        }
4858
        defo!(
4859
            "score_fixedstruct_value_not_zero ({}): score={}",
4860
            stringify!($value), $score
4861
        );
4862
    }};
4863
}
4864

4865
/// Helper to [`FixedStruct::score_fixedstruct`]
4866
/// Increase score if the ut_type is a valid value.
4867
/// Decrease score if the ut_type is a invalid value.
4868
macro_rules! score_fixedstruct_ut_type {
4869
    ($score:ident, $value:expr, $ut_types:expr) => {{
4870
        for ut_type in $ut_types {
4871
            if $value == ut_type {
4872
                $score += 5;
4873
                if $value != 0 {
4874
                    $score += 10;
4875
                }
4876
                break;
4877
            }
4878
        }
4879
        defo!(
4880
            "score_fixedstruct_ut_type ({}): score={}",
4881
            stringify!($value), $score
4882
        );
4883
    }};
4884
}
4885

4886
/// Helper to [`FixedStruct::score_fixedstruct`]
4887
/// Increase score if the bits are valid flag(s).
4888
/// Decrease score if the bits are invalid flag(s).
4889
macro_rules! score_fixedstruct_ac_flags {
4890
    ($score:ident, $value:expr, $flags:expr) => {{
4891
        if $value == 0 {
4892
            $score += 2;
4893
        } else if (!$flags) & $value != 0 {
4894
            $score -= 30;
4895
        } else {
4896
            $score += 5;
4897
        }
4898
        defo!(
4899
            "score_fixedstruct_ac_flags ({}): score={} (value=0b{:08b}, flags=0b{:08b})",
4900
            stringify!($value), $score, $value, $flags
4901
        );
4902
    }};
4903
}
4904

4905
/// Datetime _2000-01-01 00:00:00_ is a reasonable past datetime to expect for
4906
/// FixedStruct files.
4907
/// Helper to [`score_fixedstruct_time_range`].
4908
///
4909
/// **TODO:** when were utmp/lastlog/etc. structs first introduced?
4910
const EPOCH_SECOND_LOW: tv_sec_type = 946684800;
4911

4912
/// Datetime _2038-01-19 03:14:06_ is a reasonable high datetime to expect for
4913
/// FixedStruct files.
4914
/// Helper to [`score_fixedstruct_time_range`].
4915
const EPOCH_SECOND_HIGH: tv_sec_type = 2147483647;
4916

4917
/// Helper to [`FixedStruct::score_fixedstruct`].
4918
/// Increase the score if the datetime (presumed to be Unix Epoch seconds)
4919
/// is within a reasonable range. Decrease if it's outside of that range.
4920
/// Decrease the score further if the value is zero.
4921
macro_rules! score_fixedstruct_time_range {
4922
    ($score:ident, $value:expr) => {{
4923
        // XXX: copy to local to avoid warning about alignment
4924
        let val = $value;
4925
        let value_as: tv_sec_type = match val.try_into() {
4926
            Ok(val_) => val_,
4927
            Err(_err) => {
4928
                de_err!("failed to convert {:?} to tv_sec_type; {}", val, _err);
4929

4930
                0
4931
            }
4932
        };
4933
        if (EPOCH_SECOND_LOW..=EPOCH_SECOND_HIGH).contains(&value_as) {
4934
            $score += 20;
4935
        } else {
4936
            $score -= 30;
4937
        }
4938
        if value_as == 0 {
4939
            $score -= 40;
4940
        }
4941
        defo!(
4942
            "score_fixedstruct_time_range ({}): score={}",
4943
            stringify!($value), $score
4944
        );
4945
    }};
4946
}
4947

4948
impl FixedStruct
4949
{
4950
    /// Create a new `FixedStruct`.
4951
    /// The `buffer` is passed to [`buffer_to_fixedstructptr`] which returns
4952
    /// `None` if only null bytes.
4953
    pub fn new(
582✔
4954
        fileoffset: FileOffset,
582✔
4955
        tz_offset: &FixedOffset,
582✔
4956
        buffer: &[u8],
582✔
4957
        fixedstruct_type: FixedStructType,
582✔
4958
    ) -> Result<FixedStruct, Error>
582✔
4959
    {
4960
        defn!();
582✔
4961
        let fs_ptr: FixedStructDynPtr = match buffer_to_fixedstructptr(buffer, fixedstruct_type) {
582✔
4962
            Some(val) => val,
580✔
4963
            None => {
4964
                defx!("buffer_to_fixedstructptr returned None; return None");
2✔
4965
                return Result::Err(
2✔
4966
                    Error::new(
2✔
4967
                        ErrorKind::InvalidData,
2✔
4968
                        "buffer_to_fixedstructptr returned None",
2✔
4969
                    )
2✔
4970
                );
2✔
4971
            }
4972
        };
4973
        defo!("fs_ptr {:?}", fs_ptr);
580✔
4974

4975
        FixedStruct::from_fixedstructptr(fileoffset, tz_offset, fs_ptr)
580✔
4976
    }
582✔
4977

4978
    /// Create a new `FixedStruct` from a `FixedStructDynPtr`.
4979
    pub fn from_fixedstructptr(
1,131✔
4980
        fileoffset: FileOffset,
1,131✔
4981
        tz_offset: &FixedOffset,
1,131✔
4982
        fixedstructptr: FixedStructDynPtr,
1,131✔
4983
    ) -> Result<FixedStruct, Error>
1,131✔
4984
    {
4985
        defn!("fixedstructptr {:?}", fixedstructptr);
1,131✔
4986
        let dt: DateTimeL;
4987
        let tv_sec: tv_sec_type;
4988
        let tv_usec: tv_usec_type;
4989
        let tv_pair: tv_pair_type;
4990
        let fixedstructtype: FixedStructType = fixedstructptr.fixedstruct_type();
1,131✔
4991
        let filetypefixedstruct: FileTypeFixedStruct;
4992
        match fixedstructtype {
1,131✔
4993
            FixedStructType::Fs_Freebsd_x8664_Utmpx => {
1✔
4994
                filetypefixedstruct = FileTypeFixedStruct::Utmpx;
1✔
4995
                let fixedstructptr: &freebsd_x8664::utmpx = fixedstructptr.as_freebsd_x8664_utmpx();
1✔
4996
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ut_tv.tv_sec);
1✔
4997
                tv_usec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ut_tv.tv_usec);
1✔
4998
            }
1✔
4999
            FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => {
1✔
5000
                filetypefixedstruct = FileTypeFixedStruct::Lastlog;
1✔
5001
                let fixedstructptr: &linux_arm64aarch64::lastlog = fixedstructptr.as_linux_arm64aarch64_lastlog();
1✔
5002
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ll_time);
1✔
5003
                tv_usec = 0;
1✔
5004
            }
1✔
5005
            FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => {
1✔
5006
                filetypefixedstruct = FileTypeFixedStruct::Utmpx;
1✔
5007
                let fixedstructptr: &linux_arm64aarch64::utmpx = fixedstructptr.as_linux_arm64aarch64_utmpx();
1✔
5008
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ut_tv.tv_sec);
1✔
5009
                tv_usec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ut_tv.tv_usec);
1✔
5010
            }
1✔
5011
            FixedStructType::Fs_Linux_x86_Acct => {
1✔
5012
                filetypefixedstruct = FileTypeFixedStruct::Acct;
1✔
5013
                let fixedstructptr: &linux_x86::acct = fixedstructptr.as_linux_x86_acct();
1✔
5014
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ac_btime);
1✔
5015
                tv_usec = 0;
1✔
5016
            }
1✔
5017
            FixedStructType::Fs_Linux_x86_Acct_v3 => {
1✔
5018
                filetypefixedstruct = FileTypeFixedStruct::AcctV3;
1✔
5019
                let fixedstructptr: &linux_x86::acct_v3 = fixedstructptr.as_linux_x86_acct_v3();
1✔
5020
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ac_btime);
1✔
5021
                tv_usec = 0;
1✔
5022
            }
1✔
5023
            FixedStructType::Fs_Linux_x86_Lastlog => {
8✔
5024
                filetypefixedstruct = FileTypeFixedStruct::Lastlog;
8✔
5025
                let fixedstructptr: &linux_x86::lastlog = fixedstructptr.as_linux_x86_lastlog();
8✔
5026
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ll_time);
8✔
5027
                tv_usec = 0;
8✔
5028
            }
8✔
5029
            FixedStructType::Fs_Linux_x86_Utmpx => {
1,110✔
5030
                filetypefixedstruct = FileTypeFixedStruct::Utmpx;
1,110✔
5031
                let fixedstructptr: &linux_x86::utmpx = fixedstructptr.as_linux_x86_utmpx();
1,110✔
5032
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ut_tv.tv_sec);
1,110✔
5033
                tv_usec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ut_tv.tv_usec);
1,110✔
5034
            }
1,110✔
5035
            FixedStructType::Fs_Netbsd_x8632_Acct => {
1✔
5036
                filetypefixedstruct = FileTypeFixedStruct::Acct;
1✔
5037
                let fixedstructptr: &netbsd_x8632::acct = fixedstructptr.as_netbsd_x8632_acct();
1✔
5038
                let ac_btime = fixedstructptr.ac_btime;
1✔
5039
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, ac_btime);
1✔
5040
                tv_usec = 0;
1✔
5041
            }
1✔
5042
            FixedStructType::Fs_Netbsd_x8632_Lastlogx => {
1✔
5043
                filetypefixedstruct = FileTypeFixedStruct::Lastlogx;
1✔
5044
                let fixedstructptr: &netbsd_x8632::lastlogx = fixedstructptr.as_netbsd_x8632_lastlogx();
1✔
5045
                // XXX: copy to local to avoid Issue #82523; #rust-lang/rust/82523
1✔
5046
                let tv_sec_ = fixedstructptr.ll_tv.tv_sec;
1✔
5047
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, tv_sec_);
1✔
5048
                // XXX: copy to local to avoid Issue #82523; #rust-lang/rust/82523
1✔
5049
                let tv_usec_ = fixedstructptr.ll_tv.tv_usec;
1✔
5050
                tv_usec = tv_or_err_tv_sec!(fixedstructptr,  tv_usec_);
1✔
5051
            }
1✔
5052
            FixedStructType::Fs_Netbsd_x8632_Utmpx => {
1✔
5053
                filetypefixedstruct = FileTypeFixedStruct::Utmpx;
1✔
5054
                let fixedstructptr: &netbsd_x8632::utmpx = fixedstructptr.as_netbsd_x8632_utmpx();
1✔
5055
                // XXX: copy to local to avoid Issue #82523; #rust-lang/rust/82523
1✔
5056
                let tv_sec_ = fixedstructptr.ut_tv.tv_sec;
1✔
5057
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, tv_sec_);
1✔
5058
                // XXX: copy to local to avoid Issue #82523; #rust-lang/rust/82523
1✔
5059
                let tv_usec_ = fixedstructptr.ut_tv.tv_usec;
1✔
5060
                tv_usec = tv_or_err_tv_sec!(fixedstructptr, tv_usec_);
1✔
5061
            }
1✔
5062
            FixedStructType::Fs_Netbsd_x8664_Lastlog => {
1✔
5063
                filetypefixedstruct = FileTypeFixedStruct::Lastlog;
1✔
5064
                let fixedstructptr: &netbsd_x8664::lastlog = fixedstructptr.as_netbsd_x8664_lastlog();
1✔
5065
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ll_time);
1✔
5066
                tv_usec = 0;
1✔
5067
            }
1✔
5068
            FixedStructType::Fs_Netbsd_x8664_Lastlogx => {
×
5069
                filetypefixedstruct = FileTypeFixedStruct::Lastlogx;
×
5070
                let fixedstructptr: &netbsd_x8664::lastlogx = fixedstructptr.as_netbsd_x8664_lastlogx();
×
5071
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ll_tv.tv_sec);
×
5072
                tv_usec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ll_tv.tv_usec);
×
5073
            }
×
5074
            FixedStructType::Fs_Netbsd_x8664_Utmp => {
1✔
5075
                filetypefixedstruct = FileTypeFixedStruct::Utmp;
1✔
5076
                let fixedstructptr: &netbsd_x8664::utmp = fixedstructptr.as_netbsd_x8664_utmp();
1✔
5077
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ut_time);
1✔
5078
                tv_usec = 0;
1✔
5079
            }
1✔
5080
            FixedStructType::Fs_Netbsd_x8664_Utmpx => {
1✔
5081
                filetypefixedstruct = FileTypeFixedStruct::Utmpx;
1✔
5082
                let fixedstructptr: &netbsd_x8664::utmpx = fixedstructptr.as_netbsd_x8664_utmpx();
1✔
5083
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ut_tv.tv_sec);
1✔
5084
                tv_usec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ut_tv.tv_usec);
1✔
5085
            }
1✔
5086
            FixedStructType::Fs_Openbsd_x86_Lastlog => {
1✔
5087
                filetypefixedstruct = FileTypeFixedStruct::Lastlog;
1✔
5088
                let fixedstructptr: &openbsd_x86::lastlog = fixedstructptr.as_openbsd_x86_lastlog();
1✔
5089
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ll_time);
1✔
5090
                tv_usec = 0;
1✔
5091
            }
1✔
5092
            FixedStructType::Fs_Openbsd_x86_Utmp => {
1✔
5093
                filetypefixedstruct = FileTypeFixedStruct::Utmp;
1✔
5094
                let fixedstructptr: &openbsd_x86::utmp = fixedstructptr.as_openbsd_x86_utmp();
1✔
5095
                tv_sec = tv_or_err_tv_sec!(fixedstructptr, fixedstructptr.ut_time);
1✔
5096
                tv_usec = 0;
1✔
5097
            }
1✔
5098
        }
5099
        dt = tv_to_datetime_or_err!(tv_sec, tv_usec, tz_offset);
1,131✔
5100
        defo!("FixedStruct {{ dt {:?} }}", dt);
1,131✔
5101
        tv_pair = tv_pair_type(tv_sec, tv_usec);
1,131✔
5102
        defx!("FixedStruct {{ tv_pair {:?} }}", tv_pair);
1,131✔
5103
        Result::Ok(
1,131✔
5104
            FixedStruct {
1,131✔
5105
                fixedstructptr,
1,131✔
5106
                fixedstructtype,
1,131✔
5107
                filetypefixedstruct,
1,131✔
5108
                fileoffset,
1,131✔
5109
                dt,
1,131✔
5110
                tv_pair,
1,131✔
5111
            }
1,131✔
5112
        )
1,131✔
5113
    }
1,131✔
5114

5115
    pub fn len(self: &FixedStruct) -> usize
4,003✔
5116
    {
5117
        self.fixedstructptr.size()
4,003✔
5118
    }
4,003✔
5119

5120
    /// Clippy recommends `fn is_empty` since there is a `len()`.
5121
    pub fn is_empty(self: &FixedStruct) -> bool
×
5122
    {
5123
        self.len() == 0
×
5124
    }
×
5125

5126
    /// [`FileOffset`] at beginning of the `FixedStruct` (inclusive).
5127
    ///
5128
    /// [`FileOffset`]: crate::common::FileOffset
5129
    pub const fn fileoffset_begin(self: &FixedStruct) -> FileOffset
5,150✔
5130
    {
5131
        self.fileoffset
5,150✔
5132
    }
5,150✔
5133

5134
    /// [`FileOffset`] at one byte past ending of the `FixedStruct` (exclusive).
5135
    ///
5136
    /// [`FileOffset`]: crate::common::FileOffset
5137
    pub fn fileoffset_end(self: &FixedStruct) -> FileOffset
4,003✔
5138
    {
5139
        self.fileoffset + (self.len() as FileOffset)
4,003✔
5140
    }
4,003✔
5141

5142
    /// First [`BlockOffset`] of underlying [`Block`s] for the given
5143
    /// [`BlockSz`].
5144
    ///
5145
    /// [`BlockOffset`]: crate::readers::blockreader::BlockOffset
5146
    /// [`Block`s]: crate::readers::blockreader::Block
5147
    /// [`BlockSz`]: crate::readers::blockreader::BlockSz
5148
    pub const fn blockoffset_begin(&self, blocksz: BlockSz) -> BlockOffset {
2,067✔
5149
        BlockReader::block_offset_at_file_offset(
2,067✔
5150
            self.fileoffset_begin(),
2,067✔
5151
            blocksz
2,067✔
5152
        )
5153
    }
2,067✔
5154

5155
    /// Last [`BlockOffset`] of underlying [`Block`s] for the given
5156
    /// [`BlockSz`] (inclusive).
5157
    ///
5158
    /// [`BlockOffset`s]: crate::readers::blockreader::BlockOffset
5159
    /// [`Block`s]: crate::readers::blockreader::Block
5160
    /// [`BlockSz`]: crate::readers::blockreader::BlockSz
5161
    pub fn blockoffset_end(&self, blocksz: BlockSz) -> BlockOffset {
2,067✔
5162
        BlockReader::block_offset_at_file_offset(
2,067✔
5163
            self.fileoffset_end(),
2,067✔
5164
            blocksz
2,067✔
5165
        )
5166
    }
2,067✔
5167

5168
    /// Return a reference to [`self.dt`].
5169
    ///
5170
    /// [`self.dt`]: FixedStruct::dt
5171
    pub const fn dt(self: &FixedStruct) -> &DateTimeL
75,671✔
5172
    {
5173
        &self.dt
75,671✔
5174
    }
75,671✔
5175

5176
    /// Return a reference to [`self.tv_pair`].
5177
    ///
5178
    /// [`self.tv_pair`]: FixedStruct::tv_pair
5179
    pub const fn tv_pair(self: &FixedStruct) -> &tv_pair_type
1✔
5180
    {
5181
        &self.tv_pair
1✔
5182
    }
1✔
5183

5184
    /// Create a score for this FixedStruct entry
5185
    ///
5186
    /// The scoring system is a simple heuristic to determine the likelihood that
5187
    /// the FixedStruct entry is a valid version of the given `FixedStructType`.
5188
    /// The particulars of the score are just a guess; they seemed to work well in limited
5189
    /// testing.
5190
    ///
5191
    /// Scoring is necessary because a file's exact fixedstruct type often
5192
    /// cannot be determined from the name and file size alone.
5193
    ///
5194
    /// This function is used by [`FixedStructReader::score_file`].
5195
    ///
5196
    /// [`FixedStructReader::score_file`]: crate::readers::fixedstructreader::FixedStructReader::score_file
5197
    // XXX: I considered also checking for matching platform. However, the platforms
5198
    //      embedded in each namespace, e.g. `linux_x86`, may be the same for many
5199
    //      platforms, e.g. `linux_x86` may be used for both 32-bit and 64-bit x86, and on various
5200
    //      ARM and RISC architectures.
5201
    pub fn score_fixedstruct(fixedstructptr: &FixedStructDynPtr, bonus: Score) -> Score {
2,343✔
5202
        defn!();
2,343✔
5203
        defo!("fixedstructptr.entry_type() = {:?}", fixedstructptr.fixedstruct_type());
2,343✔
5204
        defo!("fixedstructptr.size() = {:?}", fixedstructptr.size());
2,343✔
5205
        let mut score: Score = 0;
2,343✔
5206
        defo!("score = {:?}", score);
2,343✔
5207
        if bonus > 0 {
2,343✔
5208
            score += bonus;
217✔
5209
            defo!("score += bonus {:?}", score);
217✔
5210
        }
2,126✔
5211
        match fixedstructptr.fixedstruct_type() {
2,343✔
5212
            FixedStructType::Fs_Freebsd_x8664_Utmpx => {
5213
                let utmpx: &freebsd_x8664::utmpx = fixedstructptr.as_freebsd_x8664_utmpx();
3✔
5214
                score_fixedstruct_cstr!(score, utmpx.ut_user());
3✔
5215
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_user);
3✔
5216
                score_fixedstruct_cstr_null_terminator!(score, utmpx.ut_user);
3✔
5217

5218
                score_fixedstruct_cstr!(score, utmpx.ut_line());
3✔
5219
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_line);
3✔
5220

5221
                score_fixedstruct_cstr!(score, utmpx.ut_host());
3✔
5222
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_host);
3✔
5223
                score_fixedstruct_cstr_null_terminator!(score, utmpx.ut_host);
3✔
5224

5225
                score_fixedstruct_time_range!(score, utmpx.ut_tv.tv_sec);
3✔
5226

5227
                score_fixedstruct_buffer_all_null!(score, utmpx.__ut_spare);
3✔
5228

5229
                score_fixedstruct_ut_type!(score, utmpx.ut_type, freebsd_x8664::UT_TYPES);
12✔
5230
            }
5231
            FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => {
5232
                let lastlog: &linux_arm64aarch64::lastlog = fixedstructptr.as_linux_arm64aarch64_lastlog();
2✔
5233

5234
                score_fixedstruct_cstr!(score, lastlog.ll_line());
2✔
5235
                score_fixedstruct_cstr_no_data_after_null!(score, lastlog.ll_line);
2✔
5236

5237
                score_fixedstruct_cstr!(score, lastlog.ll_host());
2✔
5238
                score_fixedstruct_cstr_no_data_after_null!(score, lastlog.ll_host);
2✔
5239
                score_fixedstruct_cstr_null_terminator!(score, lastlog.ll_host);
2✔
5240

5241
                score_fixedstruct_time_range!(score, lastlog.ll_time);
2✔
5242
            }
5243
            FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => {
5244
                let utmpx: &linux_arm64aarch64::utmpx = fixedstructptr.as_linux_arm64aarch64_utmpx();
2✔
5245

5246
                score_fixedstruct_cstr!(score, utmpx.ut_line());
2✔
5247
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_line);
2✔
5248

5249
                score_fixedstruct_cstr!(score, utmpx.ut_user());
2✔
5250
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_user);
2✔
5251

5252
                score_fixedstruct_cstr!(score, utmpx.ut_host());
2✔
5253
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_host);
2✔
5254
                score_fixedstruct_cstr_null_terminator!(score, utmpx.ut_host);
2✔
5255

5256
                score_fixedstruct_time_range!(score, utmpx.ut_tv.tv_sec);
2✔
5257

5258
                score_fixedstruct_buffer_all_null!(score, utmpx.__glibc_reserved);
2✔
5259

5260
                score_fixedstruct_ut_type!(score, utmpx.ut_type, linux_arm64aarch64::UT_TYPES);
6✔
5261
            }
5262
            FixedStructType::Fs_Linux_x86_Acct => {
5263
                let acct: &linux_x86::acct = fixedstructptr.as_linux_x86_acct();
582✔
5264

5265
                score_fixedstruct_cstr!(score, acct.ac_comm());
582✔
5266
                score_fixedstruct_cstr_no_data_after_null!(score, acct.ac_comm);
582✔
5267

5268
                score_fixedstruct_time_range!(score, acct.ac_btime);
582✔
5269

5270
                score_fixedstruct_buffer_all_null!(score, acct.ac_pad);
582✔
5271

5272
                score_fixedstruct_ac_flags!(score, acct.ac_flag, linux_x86::AC_FLAGS_MASK);
582✔
5273
            }
5274
            FixedStructType::Fs_Linux_x86_Acct_v3 => {
5275
                let acct: &linux_x86::acct_v3 = fixedstructptr.as_linux_x86_acct_v3();
582✔
5276

5277
                score_fixedstruct_cstr!(score, acct.ac_comm());
582✔
5278
                score_fixedstruct_cstr_no_data_after_null!(score, acct.ac_comm);
582✔
5279

5280
                score_fixedstruct_time_range!(score, acct.ac_btime);
582✔
5281

5282
                score_fixedstruct_value_not_zero!(score, acct.ac_version);
582✔
5283

5284
                score_fixedstruct_ac_flags!(score, acct.ac_flag, linux_x86::AC_FLAGS_MASK);
582✔
5285
            }
5286
            FixedStructType::Fs_Linux_x86_Lastlog => {
5287
                let lastlog: &linux_x86::lastlog = fixedstructptr.as_linux_x86_lastlog();
9✔
5288

5289
                score_fixedstruct_time_range!(score, lastlog.ll_time);
9✔
5290

5291
                score_fixedstruct_cstr!(score, lastlog.ll_line());
9✔
5292
                score_fixedstruct_cstr_no_data_after_null!(score, lastlog.ll_line);
9✔
5293

5294
                score_fixedstruct_cstr!(score, lastlog.ll_host());
9✔
5295
                score_fixedstruct_cstr_no_data_after_null!(score, lastlog.ll_host);
9✔
5296
                score_fixedstruct_cstr_null_terminator!(score, lastlog.ll_host);
9✔
5297
            }
5298
            FixedStructType::Fs_Linux_x86_Utmpx => {
5299
                let utmpx: &linux_x86::utmpx = fixedstructptr.as_linux_x86_utmpx();
566✔
5300

5301
                score_fixedstruct_cstr!(score, utmpx.ut_line());
566✔
5302
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_line);
566✔
5303

5304
                score_fixedstruct_cstr!(score, utmpx.ut_id());
566✔
5305
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_id);
566✔
5306

5307
                score_fixedstruct_cstr!(score, utmpx.ut_user());
566✔
5308
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_user);
566✔
5309
                score_fixedstruct_cstr_null_terminator!(score, utmpx.ut_user);
566✔
5310

5311
                score_fixedstruct_cstr!(score, utmpx.ut_host());
566✔
5312
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_host);
566✔
5313
                score_fixedstruct_cstr_null_terminator!(score, utmpx.ut_host);
566✔
5314

5315
                score_fixedstruct_time_range!(score, utmpx.ut_tv.tv_sec);
566✔
5316

5317
                score_fixedstruct_buffer_all_null!(score, utmpx.__glibc_reserved);
566✔
5318

5319
                score_fixedstruct_ut_type!(score, utmpx.ut_type, linux_x86::UT_TYPES);
4,240✔
5320
            }
5321
            FixedStructType::Fs_Netbsd_x8632_Acct => {
5322
                let acct: &netbsd_x8632::acct = fixedstructptr.as_netbsd_x8632_acct();
2✔
5323

5324
                score_fixedstruct_cstr!(score, acct.ac_comm());
2✔
5325
                score_fixedstruct_cstr_no_data_after_null!(score, acct.ac_comm);
2✔
5326

5327
                score_fixedstruct_time_range!(score, acct.ac_btime);
2✔
5328

5329
                score_fixedstruct_buffer_all_null!(score, acct.__gap1);
2✔
5330
                score_fixedstruct_buffer_all_null!(score, acct.__gap3);
2✔
5331

5332
                score_fixedstruct_ac_flags!(score, acct.ac_flag, netbsd_x8632::AC_FLAGS_MASK);
2✔
5333
            }
5334
            FixedStructType::Fs_Netbsd_x8632_Lastlogx => {
5335
                let lastlogx: &netbsd_x8632::lastlogx = fixedstructptr.as_netbsd_x8632_lastlogx();
2✔
5336

5337
                score_fixedstruct_cstr!(score, lastlogx.ll_line());
2✔
5338
                score_fixedstruct_cstr_no_data_after_null!(score, lastlogx.ll_line);
2✔
5339

5340
                score_fixedstruct_cstr!(score, lastlogx.ll_host());
2✔
5341
                score_fixedstruct_cstr_no_data_after_null!(score, lastlogx.ll_host);
2✔
5342
                score_fixedstruct_cstr_null_terminator!(score, lastlogx.ll_host);
2✔
5343

5344
                score_fixedstruct_time_range!(score, lastlogx.ll_tv.tv_sec);
2✔
5345
            }
5346
            FixedStructType::Fs_Netbsd_x8632_Utmpx => {
5347
                let utmpx: &netbsd_x8632::utmpx = fixedstructptr.as_netbsd_x8632_utmpx();
2✔
5348

5349
                score_fixedstruct_cstr!(score, utmpx.ut_name());
2✔
5350
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_name);
2✔
5351

5352
                score_fixedstruct_cstr!(score, utmpx.ut_id());
2✔
5353
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_id);
2✔
5354

5355
                score_fixedstruct_cstr!(score, utmpx.ut_line());
2✔
5356
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_line);
2✔
5357
                score_fixedstruct_cstr_null_terminator!(score, utmpx.ut_line);
2✔
5358

5359
                score_fixedstruct_cstr!(score, utmpx.ut_host());
2✔
5360
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_host);
2✔
5361
                score_fixedstruct_cstr_null_terminator!(score, utmpx.ut_host);
2✔
5362

5363
                score_fixedstruct_time_range!(score, utmpx.ut_tv.tv_sec);
2✔
5364

5365
                score_fixedstruct_buffer_all_null!(score, utmpx.ut_pad);
2✔
5366

5367
                score_fixedstruct_ut_type!(score, utmpx.ut_type, netbsd_x8632::UT_TYPES);
14✔
5368
            }
5369
            FixedStructType::Fs_Netbsd_x8664_Lastlog => {
5370
                let lastlog: &netbsd_x8664::lastlog = fixedstructptr.as_netbsd_x8664_lastlog();
582✔
5371

5372
                score_fixedstruct_cstr!(score, lastlog.ll_line());
582✔
5373
                score_fixedstruct_cstr_no_data_after_null!(score, lastlog.ll_line);
582✔
5374

5375
                score_fixedstruct_cstr!(score, lastlog.ll_host());
582✔
5376
                score_fixedstruct_cstr_no_data_after_null!(score, lastlog.ll_host);
582✔
5377

5378
                score_fixedstruct_time_range!(score, lastlog.ll_time);
582✔
5379
            }
5380
            FixedStructType::Fs_Netbsd_x8664_Lastlogx => {
5381
                let lastlogx: &netbsd_x8664::lastlogx = fixedstructptr.as_netbsd_x8664_lastlogx();
1✔
5382

5383
                score_fixedstruct_cstr!(score, lastlogx.ll_line());
1✔
5384
                score_fixedstruct_cstr_no_data_after_null!(score, lastlogx.ll_line);
1✔
5385

5386
                score_fixedstruct_cstr!(score, lastlogx.ll_host());
1✔
5387
                score_fixedstruct_cstr_no_data_after_null!(score, lastlogx.ll_host);
1✔
5388
                score_fixedstruct_cstr_null_terminator!(score, lastlogx.ll_host);
1✔
5389

5390
                score_fixedstruct_time_range!(score, lastlogx.ll_tv.tv_sec);
1✔
5391
            }
5392
            FixedStructType::Fs_Netbsd_x8664_Utmp => {
5393
                let utmp: &netbsd_x8664::utmp = fixedstructptr.as_netbsd_x8664_utmp();
2✔
5394

5395
                score_fixedstruct_cstr!(score, utmp.ut_line());
2✔
5396
                score_fixedstruct_cstr_no_data_after_null!(score, utmp.ut_line);
2✔
5397

5398
                score_fixedstruct_cstr!(score, utmp.ut_name());
2✔
5399
                score_fixedstruct_cstr_no_data_after_null!(score, utmp.ut_name);
2✔
5400

5401
                score_fixedstruct_cstr!(score, utmp.ut_host());
2✔
5402
                score_fixedstruct_cstr_no_data_after_null!(score, utmp.ut_host);
2✔
5403
                score_fixedstruct_cstr_null_terminator!(score, utmp.ut_host);
2✔
5404

5405
                score_fixedstruct_time_range!(score, utmp.ut_time);
2✔
5406
            }
5407
            FixedStructType::Fs_Netbsd_x8664_Utmpx => {
5408
                let utmpx: &netbsd_x8664::utmpx = fixedstructptr.as_netbsd_x8664_utmpx();
2✔
5409

5410
                score_fixedstruct_cstr!(score, utmpx.ut_user());
2✔
5411
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_user);
2✔
5412

5413
                score_fixedstruct_cstr!(score, utmpx.ut_id());
2✔
5414
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_id);
2✔
5415

5416
                score_fixedstruct_cstr!(score, utmpx.ut_line());
2✔
5417
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_line);
2✔
5418

5419
                score_fixedstruct_cstr!(score, utmpx.ut_host());
2✔
5420
                score_fixedstruct_cstr_no_data_after_null!(score, utmpx.ut_host);
2✔
5421
                score_fixedstruct_cstr_null_terminator!(score, utmpx.ut_host);
2✔
5422

5423
                score_fixedstruct_time_range!(score, utmpx.ut_tv.tv_sec);
2✔
5424

5425
                score_fixedstruct_buffer_all_null!(score, utmpx.__gap1);
2✔
5426
                score_fixedstruct_buffer_all_null!(score, utmpx.ut_pad);
2✔
5427

5428
                score_fixedstruct_ut_type!(score, utmpx.ut_type, netbsd_x8664::UT_TYPES);
16✔
5429
            }
5430
            FixedStructType::Fs_Openbsd_x86_Lastlog => {
5431
                let lastlog: &openbsd_x86::lastlog = fixedstructptr.as_openbsd_x86_lastlog();
2✔
5432

5433
                score_fixedstruct_time_range!(score, lastlog.ll_time);
2✔
5434

5435
                score_fixedstruct_cstr!(score, lastlog.ll_line());
2✔
5436
                score_fixedstruct_cstr_no_data_after_null!(score, lastlog.ll_line);
2✔
5437

5438
                score_fixedstruct_cstr!(score, lastlog.ll_host());
2✔
5439
                score_fixedstruct_cstr_no_data_after_null!(score, lastlog.ll_host);
2✔
5440
                score_fixedstruct_cstr_null_terminator!(score, lastlog.ll_host);
2✔
5441
            }
5442
            FixedStructType::Fs_Openbsd_x86_Utmp => {
5443
                let utmp: &openbsd_x86::utmp = fixedstructptr.as_openbsd_x86_utmp();
2✔
5444

5445
                score_fixedstruct_cstr!(score, utmp.ut_line());
2✔
5446
                score_fixedstruct_cstr_no_data_after_null!(score, utmp.ut_line);
2✔
5447

5448
                score_fixedstruct_cstr!(score, utmp.ut_name());
2✔
5449
                score_fixedstruct_cstr_no_data_after_null!(score, utmp.ut_name);
2✔
5450

5451
                score_fixedstruct_cstr!(score, utmp.ut_host());
2✔
5452
                score_fixedstruct_cstr_no_data_after_null!(score, utmp.ut_host);
2✔
5453
                score_fixedstruct_cstr_null_terminator!(score, utmp.ut_host);
2✔
5454

5455
                score_fixedstruct_time_range!(score, utmp.ut_time);
2✔
5456
            }
5457
        }
5458

5459
        defx!("return score {}", score);
2,343✔
5460

5461
        score
2,343✔
5462
    }
2,343✔
5463

5464
    /// Efficient function to copy the `FixedStruct` into a single re-usable
5465
    /// buffer for printing.
5466
    ///
5467
    /// Copy the `FixedStruct` into the passed `buffer` as printable bytes.
5468
    /// When successful, returns a [`InfoAsBytes::Ok`] variant with
5469
    /// number of bytes copied, start index of datetime substring, and
5470
    /// end index of datetime substring.
5471
    ///
5472
    /// If copying fails, returns a [`InfoAsBytes::Fail`] variant with
5473
    /// number of bytes copied.
5474
    pub fn as_bytes(self: &FixedStruct, buffer: &mut [u8]) -> InfoAsBytes
935✔
5475
    {
5476
        let entry: &FixedStructDynPtr = &self.fixedstructptr;
935✔
5477
        let mut at: usize = 0;
935✔
5478
        let dt_beg: BufIndex;
5479
        let dt_end: BufIndex;
5480

5481
        match entry.fixedstruct_type() {
935✔
5482
            FixedStructType::Fs_Freebsd_x8664_Utmpx => {
5483
                let utmpx: &freebsd_x8664::utmpx = entry.as_freebsd_x8664_utmpx();
1✔
5484

5485
                // ut_type
5486
                set_buffer_at_or_err_str!(buffer, at, "ut_type ");
1✔
5487
                set_buffer_at_or_err_ut_type_i16!(buffer, at, utmpx.ut_type);
1✔
5488
                // ut_tv
5489
                set_buffer_at_or_err_str!(buffer, at,  " ut_tv ");
1✔
5490
                dt_beg = at;
1✔
5491
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_tv.tv_sec, freebsd_x8664::time_t);
1✔
5492
                set_buffer_at_or_err_u8!(buffer, at, b'.');
1✔
5493
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_tv.tv_usec, freebsd_x8664::subseconds_t);
1✔
5494
                dt_end = at;
1✔
5495
                // ut_id
5496
                set_buffer_at_or_err_str!(buffer, at, " ut_id '");
1✔
5497
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_id);
1✔
5498
                // ut_pid
5499
                set_buffer_at_or_err_str!(buffer, at, "' ut_pid ");
1✔
5500
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_pid, freebsd_x8664::pid_t);
1✔
5501
                // ut_user
5502
                set_buffer_at_or_err_str!(buffer, at, " ut_user '");
1✔
5503
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_user);
1✔
5504
                // ut_line
5505
                set_buffer_at_or_err_str!(buffer, at, "' ut_line ");
1✔
5506
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_line);
1✔
5507
                // ut_host
5508
                set_buffer_at_or_err_str!(buffer, at, "' ut_host '");
1✔
5509
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_host);
1✔
5510
                set_buffer_at_or_err_u8!(buffer, at, b'\'');
1✔
5511
            }
5512
            FixedStructType::Fs_Linux_Arm64Aarch64_Lastlog => {
5513
                let lastlog: &linux_arm64aarch64::lastlog = entry.as_linux_arm64aarch64_lastlog();
1✔
5514

5515
                // ll_time
5516
                set_buffer_at_or_err_str!(buffer, at, "ll_time ");
1✔
5517
                dt_beg = at;
1✔
5518
                set_buffer_at_or_err_number!(buffer, at, lastlog.ll_time, linux_arm64aarch64::ll_time_t);
1✔
5519
                dt_end = at;
1✔
5520
                // ll_line
5521
                set_buffer_at_or_err_str!(buffer, at, " ll_line '");
1✔
5522
                set_buffer_at_or_err_cstrn!(buffer, at, lastlog.ll_line);
1✔
5523
                // ll_host
5524
                set_buffer_at_or_err_str!(buffer, at, "' ll_host '");
1✔
5525
                set_buffer_at_or_err_cstrn!(buffer, at, lastlog.ll_host);
1✔
5526
                set_buffer_at_or_err_u8!(buffer, at, b'\'');
1✔
5527
            }
5528
            FixedStructType::Fs_Linux_Arm64Aarch64_Utmpx => {
5529
                let utmpx: &linux_arm64aarch64::utmpx = entry.as_linux_arm64aarch64_utmpx();
1✔
5530

5531
                // ut_type
5532
                set_buffer_at_or_err_str!(buffer, at, "ut_type ");
1✔
5533
                set_buffer_at_or_err_ut_type_i16!(buffer, at, utmpx.ut_type);
1✔
5534
                // ut_pid
5535
                set_buffer_at_or_err_str!(buffer, at, " ut_pid ");
1✔
5536
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_pid, linux_arm64aarch64::pid_t);
1✔
5537
                // ut_line
5538
                set_buffer_at_or_err_str!(buffer, at, " ut_line '");
1✔
5539
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_line);
1✔
5540
                // ut_id
5541
                set_buffer_at_or_err_str!(buffer, at, "' ut_id '");
1✔
5542
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_id);
1✔
5543
                // ut_user
5544
                set_buffer_at_or_err_str!(buffer, at, "' ut_user '");
1✔
5545
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_user);
1✔
5546
                // ut_host
5547
                set_buffer_at_or_err_str!(buffer, at, "' ut_host '");
1✔
5548
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_host);
1✔
5549
                // ut_exit
5550
                set_buffer_at_or_err_str!(buffer, at, "' ut_exit ");
1✔
5551
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_exit, i32);
1✔
5552
                // ut_session
5553
                set_buffer_at_or_err_str!(buffer, at, " ut_session '");
1✔
5554
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_session, i64);
1✔
5555
                // ut_tv.tv_sec
5556
                set_buffer_at_or_err_str!(buffer, at, "' ut_tv ");
1✔
5557
                dt_beg = at;
1✔
5558
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_tv.tv_sec, i64);
1✔
5559
                set_buffer_at_or_err_u8!(buffer, at, b'.');
1✔
5560
                // ut_tv.tv_usec
5561
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_tv.tv_usec, i64);
1✔
5562
                dt_end = at;
1✔
5563
                // if ut_addr_v6 is all zeros then this is an IPv4 address
5564
                if utmpx.ut_addr_v6[1..4].iter().all(|&x| x == 0) {
3✔
5565
                    // ut_addr
5566
                    set_buffer_at_or_err_str!(buffer, at, " ut_addr ");
1✔
5567
                    set_buffer_at_or_err_ipv4!(buffer, at, utmpx.ut_addr_v6[0]);
1✔
5568
                } else {
5569
                    // ut_addr_v6
5570
                    set_buffer_at_or_err_str!(buffer, at, " ut_addr_v6 ");
×
5571
                    set_buffer_at_or_err_ipv6!(buffer, at, utmpx.ut_addr_v6);
×
5572
                }
5573
            }
5574
            FixedStructType::Fs_Linux_x86_Acct => {
5575
                let acct: &linux_x86::acct = entry.as_linux_x86_acct();
1✔
5576

5577
                // ac_flag
5578
                set_buffer_at_or_err_str!(buffer, at, "ac_flag ");
1✔
5579
                set_buffer_at_or_err_number_bin4!(buffer, at, acct.ac_flag, linux_x86::c_char);
1✔
5580
                if acct.ac_flag != 0 {
1✔
5581
                    set_buffer_at_or_err_str!(buffer, at, " (");
1✔
5582
                    if acct.ac_flag & linux_x86::AFORK != 0 {
1✔
5583
                        set_buffer_at_or_err_str!(buffer, at, "AFORK|");
×
5584
                    }
1✔
5585
                    if acct.ac_flag & linux_x86::ASU != 0 {
1✔
5586
                        set_buffer_at_or_err_str!(buffer, at, "ASU|");
1✔
5587
                    }
×
5588
                    if acct.ac_flag & linux_x86::ACOMPAT != 0 {
1✔
5589
                        set_buffer_at_or_err_str!(buffer, at, "ACOMPAT|");
×
5590
                    }
1✔
5591
                    if acct.ac_flag & linux_x86::ACORE != 0 {
1✔
5592
                        set_buffer_at_or_err_str!(buffer, at, "ACORE|");
×
5593
                    }
1✔
5594
                    if acct.ac_flag & linux_x86::AXSIG != 0 {
1✔
5595
                        set_buffer_at_or_err_str!(buffer, at, "AXSIG|");
×
5596
                    }
1✔
5597
                    // overwrite trailing '|' with ')'
5598
                    if buffer[at - 1] == b'|' {
1✔
5599
                        at -= 1;
1✔
5600
                    }
1✔
5601
                    set_buffer_at_or_err_str!(buffer, at, ")");
1✔
5602
                }
×
5603
                // ac_uid
5604
                set_buffer_at_or_err_str!(buffer, at, " ac_uid ");
1✔
5605
                set_buffer_at_or_err_number!(buffer, at, acct.ac_uid, linux_x86::uint16_t);
1✔
5606
                // ac_gid
5607
                set_buffer_at_or_err_str!(buffer, at, " ac_gid ");
1✔
5608
                set_buffer_at_or_err_number!(buffer, at, acct.ac_gid, linux_x86::uint16_t);
1✔
5609
                // ac_tty
5610
                set_buffer_at_or_err_str!(buffer, at, " ac_tty ");
1✔
5611
                set_buffer_at_or_err_number!(buffer, at, acct.ac_tty, linux_x86::uint16_t);
1✔
5612
                // ac_btime
5613
                set_buffer_at_or_err_str!(buffer, at, " ac_btime ");
1✔
5614
                dt_beg = at;
1✔
5615
                set_buffer_at_or_err_number!(buffer, at, acct.ac_btime, linux_x86::b_time_t);
1✔
5616
                dt_end = at;
1✔
5617
                // ac_utime
5618
                set_buffer_at_or_err_str!(buffer, at, " ac_utime ");
1✔
5619
                set_buffer_at_or_err_number!(buffer, at, acct.ac_utime, linux_x86::comp_t);
1✔
5620
                // ac_stime
5621
                set_buffer_at_or_err_str!(buffer, at, " ac_stime ");
1✔
5622
                set_buffer_at_or_err_number!(buffer, at, acct.ac_stime, linux_x86::comp_t);
1✔
5623
                // ac_etime
5624
                set_buffer_at_or_err_str!(buffer, at, " ac_etime ");
1✔
5625
                set_buffer_at_or_err_number!(buffer, at, acct.ac_etime, linux_x86::comp_t);
1✔
5626
                // ac_mem
5627
                set_buffer_at_or_err_str!(buffer, at, " ac_mem ");
1✔
5628
                set_buffer_at_or_err_number!(buffer, at, acct.ac_mem, linux_x86::comp_t);
1✔
5629
                // ac_io
5630
                set_buffer_at_or_err_str!(buffer, at, " ac_io ");
1✔
5631
                set_buffer_at_or_err_number!(buffer, at, acct.ac_io, linux_x86::comp_t);
1✔
5632
                // ac_rw
5633
                set_buffer_at_or_err_str!(buffer, at, " ac_rw ");
1✔
5634
                set_buffer_at_or_err_number!(buffer, at, acct.ac_rw, linux_x86::comp_t);
1✔
5635
                // ac_minflt
5636
                set_buffer_at_or_err_str!(buffer, at, " ac_minflt ");
1✔
5637
                set_buffer_at_or_err_number!(buffer, at, acct.ac_minflt, linux_x86::comp_t);
1✔
5638
                // ac_majflt
5639
                set_buffer_at_or_err_str!(buffer, at, " ac_majflt ");
1✔
5640
                set_buffer_at_or_err_number!(buffer, at, acct.ac_majflt, linux_x86::comp_t);
1✔
5641
                // ac_swaps
5642
                set_buffer_at_or_err_str!(buffer, at, " ac_swaps ");
1✔
5643
                set_buffer_at_or_err_number!(buffer, at, acct.ac_swaps, linux_x86::comp_t);
1✔
5644
                // ac_exitcode
5645
                set_buffer_at_or_err_str!(buffer, at, " ac_exitcode ");
1✔
5646
                set_buffer_at_or_err_number!(buffer, at, acct.ac_exitcode, u32);
1✔
5647
                // ac_comm
5648
                set_buffer_at_or_err_str!(buffer, at, " ac_comm '");
1✔
5649
                set_buffer_at_or_err_cstrn!(buffer, at, acct.ac_comm);
1✔
5650
                set_buffer_at_or_err_u8!(buffer, at, b'\'');
1✔
5651
            }
5652
            FixedStructType::Fs_Linux_x86_Acct_v3 => {
5653
                let acct_v3: &linux_x86::acct_v3 = entry.as_linux_x86_acct_v3();
1✔
5654

5655
                // ac_flag
5656
                set_buffer_at_or_err_str!(buffer, at, "ac_flag ");
1✔
5657
                set_buffer_at_or_err_number_bin4!(buffer, at, acct_v3.ac_flag, linux_x86::c_char);
1✔
5658
                if acct_v3.ac_flag != 0 {
1✔
5659
                    set_buffer_at_or_err_str!(buffer, at, " (");
1✔
5660
                    if acct_v3.ac_flag & linux_x86::AFORK != 0 {
1✔
5661
                        set_buffer_at_or_err_str!(buffer, at, "AFORK|");
1✔
5662
                    }
×
5663
                    if acct_v3.ac_flag & linux_x86::ASU != 0 {
1✔
5664
                        set_buffer_at_or_err_str!(buffer, at, "ASU|");
×
5665
                    }
1✔
5666
                    if acct_v3.ac_flag & linux_x86::ACOMPAT != 0 {
1✔
5667
                        set_buffer_at_or_err_str!(buffer, at, "ACOMPAT|");
×
5668
                    }
1✔
5669
                    if acct_v3.ac_flag & linux_x86::ACORE != 0 {
1✔
5670
                        set_buffer_at_or_err_str!(buffer, at, "ACORE|");
×
5671
                    }
1✔
5672
                    if acct_v3.ac_flag & linux_x86::AXSIG != 0 {
1✔
5673
                        set_buffer_at_or_err_str!(buffer, at, "AXSIG|");
×
5674
                    }
1✔
5675
                    // overwrite trailing '|' with ')'
5676
                    if buffer[at - 1] == b'|' {
1✔
5677
                        at -= 1;
1✔
5678
                    }
1✔
5679
                    set_buffer_at_or_err_str!(buffer, at, ")");
1✔
5680
                }
×
5681
                // ac_version
5682
                set_buffer_at_or_err_str!(buffer, at, " ac_version ");
1✔
5683
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_version, linux_x86::c_char);
1✔
5684
                // ac_tty
5685
                set_buffer_at_or_err_str!(buffer, at, " ac_tty ");
1✔
5686
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_tty, u16);
1✔
5687
                // ac_exitcode
5688
                set_buffer_at_or_err_str!(buffer, at, " ac_exitcode ");
1✔
5689
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_exitcode, u32);
1✔
5690
                // ac_uid
5691
                set_buffer_at_or_err_str!(buffer, at, " ac_uid ");
1✔
5692
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_uid, u32);
1✔
5693
                // ac_gid
5694
                set_buffer_at_or_err_str!(buffer, at, " ac_gid ");
1✔
5695
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_gid, u32);
1✔
5696
                // ac_pid
5697
                set_buffer_at_or_err_str!(buffer, at, " ac_pid ");
1✔
5698
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_pid, u32);
1✔
5699
                // ac_ppid
5700
                set_buffer_at_or_err_str!(buffer, at, " ac_ppid ");
1✔
5701
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_ppid, u32);
1✔
5702
                // ac_btime
5703
                set_buffer_at_or_err_str!(buffer, at, " ac_btime ");
1✔
5704
                dt_beg = at;
1✔
5705
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_btime, linux_x86::b_time_t);
1✔
5706
                dt_end = at;
1✔
5707
                // ac_etime
5708
                set_buffer_at_or_err_str!(buffer, at, " ac_etime ");
1✔
5709
                set_buffer_at_or_err_number_f32!(buffer, at, acct_v3.ac_etime, f32);
1✔
5710
                // ac_utime
5711
                set_buffer_at_or_err_str!(buffer, at, " ac_utime ");
1✔
5712
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_utime, linux_x86::comp_t);
1✔
5713
                // ac_stime
5714
                set_buffer_at_or_err_str!(buffer, at, " ac_stime ");
1✔
5715
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_stime, linux_x86::comp_t);
1✔
5716
                // ac_mem
5717
                set_buffer_at_or_err_str!(buffer, at, " ac_mem ");
1✔
5718
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_mem, linux_x86::comp_t);
1✔
5719
                // ac_io
5720
                set_buffer_at_or_err_str!(buffer, at, " ac_io ");
1✔
5721
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_io, linux_x86::comp_t);
1✔
5722
                // ac_rw
5723
                set_buffer_at_or_err_str!(buffer, at, " ac_rw ");
1✔
5724
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_rw, linux_x86::comp_t);
1✔
5725
                // ac_minflt
5726
                set_buffer_at_or_err_str!(buffer, at, " ac_minflt ");
1✔
5727
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_minflt, linux_x86::comp_t);
1✔
5728
                // ac_majflt
5729
                set_buffer_at_or_err_str!(buffer, at, " ac_majflt ");
1✔
5730
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_majflt, linux_x86::comp_t);
1✔
5731
                // ac_swaps
5732
                set_buffer_at_or_err_str!(buffer, at, " ac_swaps ");
1✔
5733
                set_buffer_at_or_err_number!(buffer, at, acct_v3.ac_swaps, linux_x86::comp_t);
1✔
5734
                // ac_comm
5735
                set_buffer_at_or_err_str!(buffer, at, " ac_comm '");
1✔
5736
                set_buffer_at_or_err_cstrn!(buffer, at, acct_v3.ac_comm);
1✔
5737
                set_buffer_at_or_err_u8!(buffer, at, b'\'');
1✔
5738
            }
5739
            FixedStructType::Fs_Linux_x86_Lastlog => {
5740
                let lastlog: &linux_x86::lastlog = entry.as_linux_x86_lastlog();
2✔
5741

5742
                // ll_time
5743
                set_buffer_at_or_err_str!(buffer, at, "ll_time ");
2✔
5744
                dt_beg = at;
2✔
5745
                set_buffer_at_or_err_number!(buffer, at, lastlog.ll_time, linux_x86::ll_time_t);
2✔
5746
                dt_end = at;
2✔
5747
                // ll_line
5748
                set_buffer_at_or_err_str!(buffer, at, " ll_line '");
2✔
5749
                set_buffer_at_or_err_cstrn!(buffer, at, lastlog.ll_line);
2✔
5750
                // ll_host
5751
                set_buffer_at_or_err_str!(buffer, at, "' ll_host '");
2✔
5752
                set_buffer_at_or_err_cstrn!(buffer, at, lastlog.ll_host);
2✔
5753
                set_buffer_at_or_err_u8!(buffer, at, b'\'');
2✔
5754
            }
5755
            FixedStructType::Fs_Linux_x86_Utmpx => {
5756
                let utmpx: &linux_x86::utmpx = entry.as_linux_x86_utmpx();
920✔
5757

5758
                // ut_type
5759
                set_buffer_at_or_err_str!(buffer, at, "ut_type ");
920✔
5760
                set_buffer_at_or_err_ut_type_i16!(buffer, at, utmpx.ut_type);
920✔
5761
                // ut_pid
5762
                set_buffer_at_or_err_str!(buffer, at, " ut_pid ");
920✔
5763
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_pid, linux_x86::pid_t);
920✔
5764
                // ut_line
5765
                set_buffer_at_or_err_str!(buffer, at, " ut_line '");
920✔
5766
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_line);
920✔
5767
                // ut_id
5768
                set_buffer_at_or_err_str!(buffer, at, "' ut_id '");
920✔
5769
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_id);
920✔
5770
                // ut_user
5771
                set_buffer_at_or_err_str!(buffer, at, "' ut_user '");
920✔
5772
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_user);
920✔
5773
                // ut_host
5774
                set_buffer_at_or_err_str!(buffer, at, "' ut_host '");
920✔
5775
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_host);
920✔
5776
                // ut_exit.e_termination
5777
                set_buffer_at_or_err_str!(buffer, at, "' e_termination ");
920✔
5778
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_exit.e_termination, i16);
920✔
5779
                // ut_exit.e_exit
5780
                set_buffer_at_or_err_str!(buffer, at, " e_exit ");
920✔
5781
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_exit.e_exit, i16);
920✔
5782
                // ut_session
5783
                set_buffer_at_or_err_str!(buffer, at, " ut_session '");
920✔
5784
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_session, i32);
920✔
5785
                // ut_tv.tv_sec
5786
                set_buffer_at_or_err_str!(buffer, at, "' ut_xtime ");
920✔
5787
                dt_beg = at;
920✔
5788
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_tv.tv_sec, i32);
920✔
5789
                set_buffer_at_or_err_u8!(buffer, at, b'.');
920✔
5790
                // ut_tv.tv_usec
5791
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_tv.tv_usec, i32);
920✔
5792
                dt_end = at;
920✔
5793
                // if ut_addr_v6 is all zeros then this is an IPv4 address
5794
                if utmpx.ut_addr_v6[1..4].iter().all(|&x| x == 0) {
2,760✔
5795
                    // ut_addr
5796
                    set_buffer_at_or_err_str!(buffer, at, " ut_addr ");
920✔
5797
                    set_buffer_at_or_err_ipv4!(buffer, at, utmpx.ut_addr_v6[0]);
920✔
5798
                } else {
5799
                    // ut_addr_v6
5800
                    set_buffer_at_or_err_str!(buffer, at, " ut_addr_v6 ");
×
5801
                    set_buffer_at_or_err_ipv6!(buffer, at, utmpx.ut_addr_v6);
×
5802
                }
5803
            }
5804
            FixedStructType::Fs_Netbsd_x8632_Acct => {
5805
                let acct: &netbsd_x8632::acct = entry.as_netbsd_x8632_acct();
1✔
5806

5807
                // ac_comm
5808
                set_buffer_at_or_err_str!(buffer, at, "ac_comm '");
1✔
5809
                set_buffer_at_or_err_cstrn!(buffer, at, acct.ac_comm);
1✔
5810
                // ac_utime
5811
                set_buffer_at_or_err_str!(buffer, at, "' ac_utime ");
1✔
5812
                // TODO: need to handle `comp_t` values specially; from `acct.h`:
5813
                //       /*
5814
                //        * Accounting structures; these use a comp_t type which is a 3 bits base 8
5815
                //        * exponent, 13 bit fraction ``floating point'' number.  Units are 1/AHZ
5816
                //        * seconds.
5817
                //        */
5818
                set_buffer_at_or_err_number!(buffer, at, acct.ac_utime, netbsd_x8632::comp_t);
1✔
5819
                // ac_stime
5820
                set_buffer_at_or_err_str!(buffer, at, " ac_stime ");
1✔
5821
                set_buffer_at_or_err_number!(buffer, at, acct.ac_stime, netbsd_x8632::comp_t);
1✔
5822
                // ac_etime
5823
                set_buffer_at_or_err_str!(buffer, at, " ac_etime ");
1✔
5824
                set_buffer_at_or_err_number!(buffer, at, acct.ac_etime, netbsd_x8632::comp_t);
1✔
5825
                // ac_btime
5826
                set_buffer_at_or_err_str!(buffer, at, " ac_btime ");
1✔
5827
                dt_beg = at;
1✔
5828
                set_buffer_at_or_err_number!(buffer, at, acct.ac_btime, netbsd_x8632::time_t);
1✔
5829
                dt_end = at;
1✔
5830
                // ac_uid
5831
                set_buffer_at_or_err_str!(buffer, at, " ac_uid ");
1✔
5832
                set_buffer_at_or_err_number!(buffer, at, acct.ac_uid, netbsd_x8632::uid_t);
1✔
5833
                // ac_gid
5834
                set_buffer_at_or_err_str!(buffer, at, " ac_gid ");
1✔
5835
                set_buffer_at_or_err_number!(buffer, at, acct.ac_gid, netbsd_x8632::gid_t);
1✔
5836
                // ac_mem
5837
                set_buffer_at_or_err_str!(buffer, at, " ac_mem ");
1✔
5838
                set_buffer_at_or_err_number!(buffer, at, acct.ac_mem, netbsd_x8632::uint16_t);
1✔
5839
                // ac_io
5840
                set_buffer_at_or_err_str!(buffer, at, " ac_io ");
1✔
5841
                set_buffer_at_or_err_number!(buffer, at, acct.ac_io, netbsd_x8632::comp_t);
1✔
5842
                // ac_tty
5843
                set_buffer_at_or_err_str!(buffer, at, " ac_tty ");
1✔
5844
                set_buffer_at_or_err_number!(buffer, at, acct.ac_tty, netbsd_x8632::dev_t);
1✔
5845
                // ac_flag is a bitfield
5846
                // see https://man.netbsd.org/acct.5
5847
                set_buffer_at_or_err_str!(buffer, at, " ac_flag ");
1✔
5848
                set_buffer_at_or_err_number_bin4!(buffer, at, acct.ac_flag, netbsd_x8632::uint8_t);
1✔
5849
                if acct.ac_flag != 0 {
1✔
5850
                    set_buffer_at_or_err_str!(buffer, at, " (");
1✔
5851
                    if acct.ac_flag & netbsd_x8632::AFORK != 0 {
1✔
5852
                        set_buffer_at_or_err_str!(buffer, at, "AFORK|");
×
5853
                    }
1✔
5854
                    if acct.ac_flag & netbsd_x8632::ASU != 0 {
1✔
5855
                        set_buffer_at_or_err_str!(buffer, at, "ASU|");
1✔
5856
                    }
×
5857
                    if acct.ac_flag & netbsd_x8632::ACOMPAT != 0 {
1✔
5858
                        set_buffer_at_or_err_str!(buffer, at, "ACOMPAT|");
×
5859
                    }
1✔
5860
                    if acct.ac_flag & netbsd_x8632::ACORE != 0 {
1✔
5861
                        set_buffer_at_or_err_str!(buffer, at, "ACORE|");
×
5862
                    }
1✔
5863
                    if acct.ac_flag & netbsd_x8632::AXSIG != 0 {
1✔
5864
                        set_buffer_at_or_err_str!(buffer, at, "AXSIG|");
×
5865
                    }
1✔
5866
                    // overwrite trailing '|' with ')'
5867
                    if buffer[at - 1] == b'|' {
1✔
5868
                        at -= 1;
1✔
5869
                    }
1✔
5870
                    set_buffer_at_or_err_str!(buffer, at, ")");
1✔
5871
                }
×
5872
            }
5873
            FixedStructType::Fs_Netbsd_x8632_Lastlogx => {
5874
                let lastlogx: &netbsd_x8632::lastlogx = entry.as_netbsd_x8632_lastlogx();
1✔
5875

5876
                // ll_tv.tv_sec
5877
                set_buffer_at_or_err_str!(buffer, at, "ll_tv ");
1✔
5878
                dt_beg = at;
1✔
5879
                set_buffer_at_or_err_number!(buffer, at, lastlogx.ll_tv.tv_sec, i64);
1✔
5880
                set_buffer_at_or_err_u8!(buffer, at, b'.');
1✔
5881
                // ll_tv.tv_usec
5882
                set_buffer_at_or_err_number!(buffer, at, lastlogx.ll_tv.tv_usec, i32);
1✔
5883
                dt_end = at;
1✔
5884
                // ll_line
5885
                set_buffer_at_or_err_str!(buffer, at, " ll_line '");
1✔
5886
                set_buffer_at_or_err_cstrn!(buffer, at, lastlogx.ll_line);
1✔
5887
                // ll_host
5888
                set_buffer_at_or_err_str!(buffer, at, "' ll_host '");
1✔
5889
                set_buffer_at_or_err_cstrn!(buffer, at, lastlogx.ll_host);
1✔
5890
                // ll_ss
5891
                set_buffer_at_or_err_str!(buffer, at, "' ll_ss ");
1✔
5892
                set_buffer_at_or_err_cstrn!(buffer, at, lastlogx.ll_ss);
1✔
5893
            }
5894
            FixedStructType::Fs_Netbsd_x8632_Utmpx => {
5895
                let utmpx: &netbsd_x8632::utmpx = entry.as_netbsd_x8632_utmpx();
1✔
5896

5897
                // ut_name
5898
                set_buffer_at_or_err_str!(buffer, at, "ut_name '");
1✔
5899
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_name);
1✔
5900
                // ut_id
5901
                set_buffer_at_or_err_str!(buffer, at, "' ut_id '");
1✔
5902
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_id);
1✔
5903
                // ut_line
5904
                set_buffer_at_or_err_str!(buffer, at, "' ut_line '");
1✔
5905
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_line);
1✔
5906
                // ut_host
5907
                set_buffer_at_or_err_str!(buffer, at, "' ut_host '");
1✔
5908
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_host);
1✔
5909
                // ut_session
5910
                set_buffer_at_or_err_str!(buffer, at, "' ut_session '");
1✔
5911
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_session, netbsd_x8632::uint16_t);
1✔
5912
                // ut_type
5913
                set_buffer_at_or_err_str!(buffer, at, "' ut_type ");
1✔
5914
                set_buffer_at_or_err_ut_type_u16!(buffer, at, utmpx.ut_type);
1✔
5915
                // ut_pid
5916
                set_buffer_at_or_err_str!(buffer, at, " ut_pid ");
1✔
5917
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_pid, netbsd_x8632::pid_t);
1✔
5918
                // ut_exit.e_termination
5919
                set_buffer_at_or_err_str!(buffer, at, " e_termination ");
1✔
5920
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_exit.e_termination, netbsd_x8632::uint16_t);
1✔
5921
                // ut_exit.e_exit
5922
                set_buffer_at_or_err_str!(buffer, at, " e_exit ");
1✔
5923
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_exit.e_exit, netbsd_x8632::uint16_t);
1✔
5924
                // ut_ss
5925
                set_buffer_at_or_err_str!(buffer, at, " ut_ss '");
1✔
5926
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_ss);
1✔
5927
                // ut_tv.tv_sec
5928
                set_buffer_at_or_err_str!(buffer, at, "' ut_tv ");
1✔
5929
                dt_beg = at;
1✔
5930
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_tv.tv_sec, i64);
1✔
5931
                set_buffer_at_or_err_u8!(buffer, at, b'.');
1✔
5932
                // ut_tv.tv_usec
5933
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_tv.tv_usec, i32);
1✔
5934
                dt_end = at;
1✔
5935
            }
5936
            FixedStructType::Fs_Netbsd_x8664_Lastlog => {
5937
                let lastlog: &netbsd_x8664::lastlog = entry.as_netbsd_x8664_lastlog();
1✔
5938

5939
                // ll_time
5940
                set_buffer_at_or_err_str!(buffer, at, "ll_time ");
1✔
5941
                dt_beg = at;
1✔
5942
                set_buffer_at_or_err_number!(buffer, at, lastlog.ll_time, netbsd_x8664::time_t);
1✔
5943
                dt_end = at;
1✔
5944
                // ll_line
5945
                set_buffer_at_or_err_str!(buffer, at, " ll_line '");
1✔
5946
                set_buffer_at_or_err_cstrn!(buffer, at, lastlog.ll_line);
1✔
5947
                // ll_host
5948
                set_buffer_at_or_err_str!(buffer, at, "' ll_host '");
1✔
5949
                set_buffer_at_or_err_cstrn!(buffer, at, lastlog.ll_host);
1✔
5950
                set_buffer_at_or_err_u8!(buffer, at, b'\'');
1✔
5951
            }
5952
            FixedStructType::Fs_Netbsd_x8664_Lastlogx => {
5953
                let lastlogx: &netbsd_x8664::lastlogx = entry.as_netbsd_x8664_lastlogx();
×
5954

5955
                // ll_tv.tv_sec
5956
                set_buffer_at_or_err_str!(buffer, at, "ll_tv ");
×
5957
                dt_beg = at;
×
5958
                set_buffer_at_or_err_number!(buffer, at, lastlogx.ll_tv.tv_sec, i64);
×
5959
                set_buffer_at_or_err_u8!(buffer, at, b'.');
×
5960
                // ll_tv.tv_usec
5961
                set_buffer_at_or_err_number!(buffer, at, lastlogx.ll_tv.tv_usec, i32);
×
5962
                dt_end = at;
×
5963
                // ll_line
5964
                set_buffer_at_or_err_str!(buffer, at, " ll_line '");
×
5965
                set_buffer_at_or_err_cstrn!(buffer, at, lastlogx.ll_line);
×
5966
                // ll_host
5967
                set_buffer_at_or_err_str!(buffer, at, "' ll_host '");
×
5968
                set_buffer_at_or_err_cstrn!(buffer, at, lastlogx.ll_host);
×
5969
                set_buffer_at_or_err_u8!(buffer, at, b'\'');
×
5970
                // XXX: ll_ss is not printable
5971
            }
5972
            FixedStructType::Fs_Netbsd_x8664_Utmp => {
5973
                let utmp: &netbsd_x8664::utmp = entry.as_netbsd_x8664_utmp();
1✔
5974

5975
                // ut_line
5976
                set_buffer_at_or_err_str!(buffer, at, "ut_line '");
1✔
5977
                set_buffer_at_or_err_cstrn!(buffer, at, utmp.ut_line);
1✔
5978
                // ut_name
5979
                set_buffer_at_or_err_str!(buffer, at, "' ut_name '");
1✔
5980
                set_buffer_at_or_err_cstrn!(buffer, at, utmp.ut_name);
1✔
5981
                // ut_host
5982
                set_buffer_at_or_err_str!(buffer, at, "' ut_host '");
1✔
5983
                set_buffer_at_or_err_cstrn!(buffer, at, utmp.ut_host);
1✔
5984
                // ut_time
5985
                set_buffer_at_or_err_str!(buffer, at, "' ut_time ");
1✔
5986
                dt_beg = at;
1✔
5987
                set_buffer_at_or_err_number!(buffer, at, utmp.ut_time, netbsd_x8664::time_t);
1✔
5988
                dt_end = at;
1✔
5989
            }
5990
            FixedStructType::Fs_Netbsd_x8664_Utmpx => {
5991
                let utmpx: &netbsd_x8664::utmpx = entry.as_netbsd_x8664_utmpx();
1✔
5992

5993
                // ut_user
5994
                set_buffer_at_or_err_str!(buffer, at, "ut_user '");
1✔
5995
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_user);
1✔
5996
                // ut_id
5997
                set_buffer_at_or_err_str!(buffer, at, "' ut_id '");
1✔
5998
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_id);
1✔
5999
                // ut_line
6000
                set_buffer_at_or_err_str!(buffer, at, "' ut_line '");
1✔
6001
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_line);
1✔
6002
                // ut_host
6003
                set_buffer_at_or_err_str!(buffer, at, "' ut_host '");
1✔
6004
                set_buffer_at_or_err_cstrn!(buffer, at, utmpx.ut_host);
1✔
6005
                // ut_session
6006
                set_buffer_at_or_err_str!(buffer, at, "' ut_session '");
1✔
6007
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_session, netbsd_x8664::uint16_t);
1✔
6008
                // ut_type
6009
                set_buffer_at_or_err_str!(buffer, at, "' ut_type ");
1✔
6010
                set_buffer_at_or_err_ut_type_u16!(buffer, at, utmpx.ut_type);
1✔
6011
                
6012
                // ut_pid
6013
                set_buffer_at_or_err_str!(buffer, at, " ut_pid ");
1✔
6014
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_pid, i32);
1✔
6015
                // ut_exit.e_termination
6016
                set_buffer_at_or_err_str!(buffer, at, " e_termination ");
1✔
6017
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_exit.e_termination, netbsd_x8664::uint16_t);
1✔
6018
                // ut_exit.e_exit
6019
                set_buffer_at_or_err_str!(buffer, at, " e_exit ");
1✔
6020
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_exit.e_exit, netbsd_x8664::uint16_t);
1✔
6021
                // ut_tv.tv_sec
6022
                set_buffer_at_or_err_str!(buffer, at, " ut_tv ");
1✔
6023
                dt_beg = at;
1✔
6024
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_tv.tv_sec, i64);
1✔
6025
                set_buffer_at_or_err_u8!(buffer, at, b'.');
1✔
6026
                set_buffer_at_or_err_number!(buffer, at, utmpx.ut_tv.tv_usec, i32);
1✔
6027
                dt_end = at;
1✔
6028
            }
6029
            FixedStructType::Fs_Openbsd_x86_Lastlog => {
6030
                let lastlog: &openbsd_x86::lastlog = entry.as_openbsd_x86_lastlog();
1✔
6031

6032
                // ll_time
6033
                set_buffer_at_or_err_str!(buffer, at, "ll_time ");
1✔
6034
                dt_beg = at;
1✔
6035
                set_buffer_at_or_err_number!(buffer, at, lastlog.ll_time, openbsd_x86::time_t);
1✔
6036
                dt_end = at;
1✔
6037
                // ll_line
6038
                set_buffer_at_or_err_str!(buffer, at, " ll_line '");
1✔
6039
                set_buffer_at_or_err_cstrn!(buffer, at, lastlog.ll_line);
1✔
6040
                // ll_host
6041
                set_buffer_at_or_err_str!(buffer, at, "' ll_host '");
1✔
6042
                set_buffer_at_or_err_cstrn!(buffer, at, lastlog.ll_host);
1✔
6043
                set_buffer_at_or_err_u8!(buffer, at, b'\'');
1✔
6044
            }
6045
            FixedStructType::Fs_Openbsd_x86_Utmp => {
6046
                let utmp: &openbsd_x86::utmp = entry.as_openbsd_x86_utmp();
1✔
6047

6048
                // ut_line
6049
                set_buffer_at_or_err_str!(buffer, at, "ut_line '");
1✔
6050
                set_buffer_at_or_err_cstrn!(buffer, at, utmp.ut_line);
1✔
6051
                // ut_name
6052
                set_buffer_at_or_err_str!(buffer, at, "' ut_name '");
1✔
6053
                set_buffer_at_or_err_cstrn!(buffer, at, utmp.ut_name);
1✔
6054
                // ut_host
6055
                set_buffer_at_or_err_str!(buffer, at, "' ut_host '");
1✔
6056
                set_buffer_at_or_err_cstrn!(buffer, at, utmp.ut_host);
1✔
6057
                // ut_time
6058
                set_buffer_at_or_err_str!(buffer, at, "' ut_time ");
1✔
6059
                dt_beg = at;
1✔
6060
                set_buffer_at_or_err_number!(buffer, at, utmp.ut_time, openbsd_x86::time_t);
1✔
6061
                dt_end = at;
1✔
6062
            }
6063
        }
6064
        // line end
6065
        set_buffer_at_or_err_u8!(buffer, at, b'\n');
935✔
6066
        // string end
6067
        set_buffer_at_or_err_u8!(buffer, at, b'\0');
935✔
6068

6069
        debug_assert_le!(dt_beg, dt_end);
935✔
6070
        debug_assert_le!(dt_end, at);
935✔
6071

6072
        InfoAsBytes::Ok(at, dt_beg, dt_end)
935✔
6073
    }
935✔
6074

6075
    /// Create `String` from known bytes.
6076
    ///
6077
    /// `raw` is `true` means use byte characters as-is.
6078
    /// `raw` is `false` means replace formatting characters or non-printable
6079
    /// characters with pictoral representation (i.e. use
6080
    /// [`byte_to_char_noraw`]).
6081
    ///
6082
    /// XXX: very inefficient and not always correct! *only* intended to help
6083
    ///      humans visually inspect stderr output.
6084
    ///
6085
    /// [`byte_to_char_noraw`]: crate::debug::printers::byte_to_char_noraw
6086
    // XXX: this function is a lot of tedious work and duplicates
6087
    //      `fmt::Debug` and `as_bytes()`; consider removing it
6088
    #[doc(hidden)]
6089
    #[allow(non_snake_case)]
6090
    #[cfg(any(debug_assertions, test))]
6091
    fn impl_to_String_raw(
1✔
6092
        self: &FixedStruct,
1✔
6093
        _raw: bool,
1✔
6094
    ) -> String
1✔
6095
    {
6096
        let mut buf: String = String::with_capacity(100);
1✔
6097
        buf.push_str("(incomplete function impl_to_String_raw)");
1✔
6098

6099
        buf
1✔
6100
    }
1✔
6101

6102
    // TODO fix non_snake_case
6103

6104
    /// `FixedStruct` to `String`.
6105
    #[doc(hidden)]
6106
    #[allow(non_snake_case)]
6107
    #[cfg(any(debug_assertions, test))]
6108
    pub fn to_String_raw(self: &FixedStruct) -> String
×
6109
    {
6110
        self.impl_to_String_raw(true)
×
6111
    }
×
6112

6113
    /// `FixedStruct` to `String` but using printable chars for
6114
    /// non-printable and/or formatting characters.
6115
    #[doc(hidden)]
6116
    #[allow(non_snake_case)]
6117
    #[cfg(any(debug_assertions, test))]
6118
    pub fn to_String_noraw(self: &FixedStruct) -> String
1✔
6119
    {
6120
        self.impl_to_String_raw(false)
1✔
6121
    }
1✔
6122
}
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