util-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Questions about util-linux
@ 2025-06-05 10:25 Nick Piaddo
  2025-06-08 21:37 ` Thomas Weißschuh
  0 siblings, 1 reply; 2+ messages in thread
From: Nick Piaddo @ 2025-06-05 10:25 UTC (permalink / raw)
  To: util-linux@vger.kernel.org

**As my first post on this mailing list, please advise if "this is NOT the way..."**

Hi,

I am developing a personal project in Rust for which I need to probe block
devices, create, and mount partitions; `libblkid`, `libfdisk`, and `libmount`
fit the bill perfectly.

So, I am writing Rust bindings for `util-linux-2.39` (published on `crates.io`):
- `rsblkid`: [crate](https://crates.io/crates/rsblkid)  [docs](https://docs.rs/rsblkid/latest/rsblkid/)
- `rsfdisk`: [crate](https://crates.io/crates/rsfdisk)  [docs](https://docs.rs/rsfdisk/latest/rsfdisk/)
- `rsmount`: [crate](https://crates.io/crates/rsmount)  [docs](https://docs.rs/rsmount/latest/rsmount/)

They are first drafts with APIs that are still in flux, with low test coverage,
and some C functions are still missing their Rust equivalents.

Even after going through:
- the source code of each C library,
- their documentation pages,
- the manpages of `blkid`,  `fdisk`, `mount`,
- and searching the net for as much information as I could find,

the docs of each crate still reflects my limited knowledge of `util-linux`.

So, I do have a few questions I hope experts on this list may be able to
answer (see further down). **Warning:** It's a long read!

Thank you for your help! (´ ˘ `ㅅ)

Nick

## How are questions structured?

Most questions follow the pattern described below:

```
<id> "-" <question>"?"
<context>
{<url>
<quote>};


<id> = <capital-letter><seq-num>;
<capital-letter> = "G" | "B" | "F" | "M";
<seq-num> = <digit>, {<digit>};
<digit> = "0" | "1" | "2" | "3" | "4" | 5 | "6" | 7 | "8" | "9";
```

- `<id>`: unique ID for each question.
- `<question>`: text describing the question.
- `<context>`: text describing the issue that prompted the question.
- `<url>`: link to a source file/documentation page of a function cited in
  `<context>`.
- `<quote>`: excerpt from documentation/source code at `<url>`.

About `<id>`:
-`<capital-letter>`: can be one of
  + `G` for a general question about `util-linux`
  + `B` for a specific question about `libblkid`
  + `F` for a specific question about `libfdisk`
  + `M` for a specific question about `libmount`
- `<seq-num>`: a sequence number.

Please mention the ID of the question you are answering, or are seeking
clarifications for. It will make the conversation easier to follow.

Thanks! (^-^)b

## General questions

G1 - Would it be possible to provide a way to define a destructor for functions
registering callbacks, long-lived or otherwise?

Interoperating with C, and registering callback functions requires Rust to
allocate state data on the heap.

From the [Rustonomicon](https://doc.rust-lang.org/nomicon/ffi.html#destructors)
we learn that:
> Foreign libraries often hand off ownership of resources to the calling code.
> When this occurs, we must use Rust's destructors to provide safety and
> guarantee the release of these resources (especially in the case of panic).

To free dynamically allocated Rust data, C functions registering callbacks
should have a signature like the one shown below:

```C
void widget_register_callback(
    widget_t *widget,
    void *data,
    void (*callback)(void*, event_t),
    void (*destroy)(void*)
);
```

See this blog post [Neat Rust Tricks: Passing Rust Closures to
C](http://blog.sagetheprogrammer.com/neat-rust-tricks-passing-rust-closures-to-c)
for a presentation of what I dream `util-linux` had. (╥﹏╥)つ

While reading `util-linux`'s source code, I identified three types of functions
to register callbacks:

- functions for which it is essentially impossible to create Rust bindings,
  case in point: `fdisk_table_sort_partitions` (see documentation further down).
  This function has a signature that looks like the example below.

  ```C
  void widget_register_callback(
      widget_t *widget,
      void (*callback)(event_t),
  );
  ```

  You will notice that it does not:
  + have a data pointer (`void *data`),
  + provide a callback function that accepts a `void*` parameter,
  + offer a way to set a destructor.

- functions for registering long-lived callbacks with a signature like the one
  shown below

  ```C
  void widget_register_callback(
      widget_t *widget,
      void (*callback)(void*, event_t),
  );
  ```
  For example, `mnt_table_set_parser_errcb` that acts on a `struct
  libmnt_table`. This structure has an internal field to store a data pointer,
  along with specialized accessor functions to get/set it (respectively
  `mnt_table_get_userdata `, and `mnt_table_set_userdata `). However, lacking a
  way to define a destructor, this function will leak memory each time it is
  called to replace a callback.

- functions for registering short-lived callbacks with a signature like the one
  shown below

  ```C
  void widget_register_callback(
      widget_t *widget,
      void *data,
      void (*callback)(void*, event_t),
  );
  ```
  For example, `mnt_table_find_next_fs` which is the closest to the ideal form.
  Although it lacks a way to define a destructor, being short-lived, it allows
  the enclosing Rust binding to take care of releasing resources allocated on
  the heap.

https://github.com/util-linux/util-linux/blob/stable/v2.39/libfdisk/src/fdiskP.h#L200-L205

```C
struct fdisk_table {
struct list_head parts; /* partitions */
int refcount;
size_t nents; /* number of partitions */
};

```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libfdisk-docs/libfdisk-Table.html#fdisk-table-sort-partitions

```text
int
fdisk_table_sort_partitions (struct fdisk_table *tb,
                             int (*cmp) (struct fdisk_partition *, struct fdisk_partition *));

Sort partition in the table.

Parameters

tb table

cmp compare function

Returns

0 on success, <0 on error.
```

https://github.com/util-linux/util-linux/blob/stable/v2.39/libmount/src/mountP.h#L249-L273

```C
/*
 * fstab/mountinfo file
 */
struct libmnt_table {
int fmt; /* MNT_FMT_* file format */
int nents; /* number of entries */
int refcount; /* reference counter */
int comms; /* enable/disable comment parsing */
char *comm_intro; /* First comment in file */
char *comm_tail; /* Last comment in file */


struct libmnt_cache *cache; /* canonicalized paths/tags cache */


        int (*errcb)(struct libmnt_table *tb,
const char *filename, int line);


int (*fltrcb)(struct libmnt_fs *fs, void *data);
void *fltrcb_data;


int noautofs; /* ignore autofs mounts */


struct list_head ents; /* list of entries (libmnt_fs) */
void *userdata;
};
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Table-of-filesystems.html#mnt-table-set-parser-errcb

```text
int
mnt_table_set_parser_errcb (struct libmnt_table *tb,
                            int (*cb) (struct libmnt_table *tb, const char *filename, int line));

The error callback function is called by table parser (mnt_table_parse_file())
in case of a syntax error. The callback function could be used for error
evaluation, libmount will continue/stop parsing according to callback return
codes:

<0 : fatal error (abort parsing) 0 : success (parsing continues) >0 :
recoverable error (the line is ignored, parsing continues).

Parameters

tb pointer to table

cb pointer to callback function

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Table-of-filesystems.html#mnt-table-get-userdata

```text
void *
mnt_table_get_userdata (struct libmnt_table *tb);

Parameters

tb pointer to tab

Returns

pointer to user's data.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Table-of-filesystems.html#mnt-table-set-userdata

```text
int
mnt_table_set_userdata (struct libmnt_table *tb,
                        void *data);

Sets pointer to the private user data.
Parameters

tb pointer to tab


data pointer to user data

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Table-of-filesystems.html#mnt-table-find-next-fs

```text
int
mnt_table_find_next_fs (struct libmnt_table *tb,
                        struct libmnt_iter *itr,
                        int (*match_func) (struct libmnt_fs *, void *),
                        void *userdata,
                        struct libmnt_fs **fs);

This function allows searching in tb .

Parameters

tb table

itr iterator

match_func function returning 1 or 0

userdata extra data for match_func

fs NULL or returns pointer to the next matching table entry

Returns

negative number in case of error, 1 at end of table or 0 o success.
```

G2 - How can I create device images that will trigger errors when running
unit-tests?

For example, files in `util-linux/tests/expected/blkid` show the expected
outputs after probing the properties of device images in
`util-linux/tests/ts/blkid/images-fs`.

Each image in the directory has a well-formed partition table, so tests will
always walk the "happy path". There is no image that could, for example,
trigger a collision error between probing results.

Rust provides its own test framework, with which it is easy to check functions
(including error cases) at a more granular level than with the test suite in
`util-linux`.

Knowing how to create an intentionally broken device image would be wonderful.
It would allow me to increase test coverage of my Rust-bindings.

## libblkid

B1 - Are there public accessor functions on the roadmap of `libblkid` for
reading the private fields `bid_pri`, `bid_devno`, and `bid_time` in
`blkid_dev_struct`?

For the moment, I can not accurately reproduce the way data about a
`blkid_struct_dev` is printed in `/run/blkid/blkid.tab` due to not being able
to access the relevant fields.

Example of a line in `/run/blkid/blkid.tab`

```text
<device DEVNO="0xfe01" TIME="1687337407.788618" PRI="45" LABEL="root" UUID="9e4adae9-4122-47fe-848f-67a9eb726207" BLOCK_SIZE="4096" TYPE="ext4">/dev/mapper/vg_nixos-root</device>
```

What I can currently output from Rust

```text
<device LABEL="root" UUID="9e4adae9-4122-47fe-848f-67a9eb726207" BLOCK_SIZE="4096" TYPE="ext4">/dev/mapper/vg_nixos-root</device>
```

https://github.com/util-linux/util-linux/blob/8aa25617467a1249669cff7240ca31973bf9a127/libblkid/src/blkidP.h#L45-L61

```C
struct blkid_struct_dev
{
struct list_head bid_devs; /* All devices in the cache */
struct list_head bid_tags; /* All tags for this device */
blkid_cache bid_cache; /* Dev belongs to this cache */
char *bid_name; /* Device real path (as used in cache) */
char *bid_xname; /* Device path as used by application (maybe symlink..) */
char *bid_type; /* Preferred device TYPE */
int bid_pri; /* Device priority */
dev_t bid_devno; /* Device major/minor number */
time_t bid_time; /* Last update time of device */
suseconds_t bid_utime; /* Last update time (microseconds) */
unsigned int bid_flags; /* Device status bitflags */
char *bid_label; /* Shortcut to device LABEL */
char *bid_uuid; /* Shortcut to binary UUID */
};
```


B2 - Does anyone know what the function `blkid_dev_set_search` is supposed to
do?

There are no docstrings for this function. Although I read its source code, I
could not figure out its purpose.  <('^-^)

https://github.com/util-linux/util-linux/blob/stable/v2.39/libblkid/src/dev.c#L150-L172

```C
int blkid_dev_set_search(blkid_dev_iterate iter,
const char *search_type, const char *search_value)
{
char *new_type, *new_value;


if (!iter || iter->magic != DEV_ITERATE_MAGIC || !search_type ||
   !search_value)
return -1;
new_type = malloc(strlen(search_type)+1);
new_value = malloc(strlen(search_value)+1);
if (!new_type || !new_value) {
free(new_type);
free(new_value);
return -1;
}
strcpy(new_type, search_type);
strcpy(new_value, search_value);
free(iter->search_type);
free(iter->search_value);
iter->search_type = new_type;
iter->search_value = new_value;
return 0;
}
```


B3 -  Do I define `size` as `uint64_t` or `int64_t`?

The `size` field in `struct blkid_struct_probe` is of type `uint64_t`. But,
according to the documentation, its accessor function `blkid_probe_get_sectors`
may return `-1` in case of error.

Reading the code of `blkid_probe_get_sectors`, I can see that it just divides
`size` by 512 which would never return a negative value (see below).

https://github.com/util-linux/util-linux/blob/stable/v2.39/libblkid/src/blkidP.h#L203-L233

```C
/*
 * Low-level probing control struct
 */
struct blkid_struct_probe
{
int fd; /* device file descriptor */
uint64_t off; /* begin of data on the device */
uint64_t size; /* end of data on the device */

dev_t devno; /* device number (st.st_rdev) */
dev_t disk_devno; /* devno of the whole-disk or 0 */
unsigned int blkssz; /* sector size (BLKSSZGET ioctl) */
mode_t mode; /* struct stat.sb_mode */
uint64_t zone_size; /* zone size (BLKGETZONESZ ioctl) */

int flags; /* private library flags */
int prob_flags; /* always zeroized by blkid_do_*() */

uint64_t wipe_off; /* begin of the wiped area */
uint64_t wipe_size; /* size of the wiped area */
struct blkid_chain *wipe_chain; /* superblock, partition, ... */

struct list_head buffers; /* list of buffers */
struct list_head hints;

struct blkid_chain chains[BLKID_NCHAINS]; /* array of chains */
struct blkid_chain *cur_chain; /* current chain */

struct list_head values; /* results */

struct blkid_struct_probe *parent; /* for clones */
struct blkid_struct_probe *disk_probe; /* whole-disk probing */
};

```

https://github.com/util-linux/util-linux/blob/stable/v2.39/libblkid/src/blkid.h.in#L85-L90

```C
/**
 * blkid_loff_t:
 *
 * 64-bit signed number for offsets and sizes
 */
typedef int64_t blkid_loff_t;
```

https://github.com/util-linux/util-linux/blob/8aa25617467a1249669cff7240ca31973bf9a127/libblkid/src/probe.c#L1971-L1983

```C
/**
 * blkid_probe_get_sectors:
 * @pr: probe
 *
 * Returns: 512-byte sector count or -1 in case of error.
 */
blkid_loff_t blkid_probe_get_sectors(blkid_probe pr)
{
return (blkid_loff_t) (pr->size >> 9);
}
```


B4 - Is the documentation out-of-date or just anticipating a future change?

The function `blkid_probe_set_sectorsize` always returns `0`, but its docstring
says otherwise.

https://github.com/util-linux/util-linux/blob/8aa25617467a1249669cff7240ca31973bf9a127/libblkid/src/probe.c#L2014-L2030

```C
/**
 * blkid_probe_set_sectorsize:
 * @pr: probe
 * @sz: new size (to overwrite system default)
 *
 * Note that blkid_probe_set_device() resets this setting. Use it after
 * blkid_probe_set_device() and before any probing call.
 *
 * Since: 2.30
 *
 * Returns: 0 or <0 in case of error
 */
int blkid_probe_set_sectorsize(blkid_probe pr, unsigned int sz)
{
pr->blkssz = sz;
return 0;
}
```


B5 - Is there a list of all file systems supported by `libblkid`?

By searching the source code, I managed to constitute a list of supported file
systems gathered in the enum
[`FileSystem`](https://docs.rs/rsblkid/latest/rsblkid/partition/enum.FileSystem.html#variants)
in `rsblkid`.

It would be nice if I could double-check its accuracy from an official
reference.


B6 - Is there a list of all tags supported by `libblkid`?

By searching the source code, I managed to constitute a list of supported tags
gathered in the enum
[`Tag`](https://docs.rs/rsblkid/latest/rsblkid/device/enum.Tag.html#variants)
in `rsblkid`.

It would be nice if I could double-check its accuracy from an official
reference.

## libfdisk

F1 - What is a `grain size`?

The documentation of `fdisk_get_grain_size` says "grain in bytes used to align
partitions (usually 1MiB)" but does not elaborate.

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libfdisk-docs/libfdisk-Context.html#fdisk-get-grain-size

I stumbled on this answer about partition alignment during my search:

"What is partition alignment and why whould I need it?"

https://superuser.com/a/393918

Is it what `fdisk_get_grain_size` is refering to?


F2 - Are `fdisk_labelitem_*` supposed to have globally unique values, or is the
overlap intentional?

The way they are currently defined `SUN_LABELITEM_LABELID`,
`BSD_LABELITEM_TYPE`,`SGI_LABELITEM_PCYLCOUNT` , and `GPT_LABELITEM_FIRSTLBA`
end up having the same numerical value i.e.  `__FDISK_NLABELITEMS = 8`.

As I understand it, these LABELITEM are fields in a partition table header for
their respective partition table types.

To represent them in Rust, I use
[HeaderEntry](https://docs.rs/rsfdisk/latest/rsfdisk/partition_table/enum.HeaderEntry.html#)
which groups the LABELITEMs in a unified enum.

This enum uses a workaround to convert a `HeaderEntry` to the native `u32`
value used by `libfdisk`
https://github.com/nickpiaddo/rsfdisk/blob/main/src/core/partition_table/header_entry_enum.rs

But converting back from `u32` to `HeaderEntry` is all but impossible if the
value of each `fdisk_labelitem_*` is not globally unique.

See their definitions below.

https://github.com/util-linux/util-linux/blob/8aa25617467a1249669cff7240ca31973bf9a127/libfdisk/src/libfdisk.h.in#L414-L425

```C
  /**
   * fdisk_labelitem_gen:
   * @FDISK_LABELITEM_ID: Unique disk identifier
   * @__FDISK_NLABELITEMS: Specifies reserved range for generic items (0..7)
   *
   * Generic disklabel items.
   */
  enum fdisk_labelitem_gen {
    FDISK_LABELITEM_ID = 0,
    __FDISK_NLABELITEMS = 8
  };
```

https://github.com/util-linux/util-linux/blob/8aa25617467a1249669cff7240ca31973bf9a127/libfdisk/src/libfdisk.h.in#L634-L655

```C
    /**
   * fdisk_labelitem_sun:
   * @SUN_LABELITEM_LABELID: Label ID
   * @SUN_LABELITEM_VTOCID: Volume ID
   * @SUN_LABELITEM_RPM: Rpm
   * @SUN_LABELITEM_ACYL: Alternate cylinders
   * @SUN_LABELITEM_PCYL: Physical cylinders
   * @SUN_LABELITEM_APC: Extra sects/cyl
   * @SUN_LABELITEM_INTRLV: Interleave
   *
   * SUN specific label items.
   */
  enum fdisk_labelitem_sun {
    SUN_LABELITEM_LABELID = __FDISK_NLABELITEMS,
    SUN_LABELITEM_VTOCID,
    SUN_LABELITEM_RPM,
    SUN_LABELITEM_ACYL,
    SUN_LABELITEM_PCYL,
    SUN_LABELITEM_APC,
    SUN_LABELITEM_INTRLV
  };

```

https://github.com/util-linux/util-linux/blob/8aa25617467a1249669cff7240ca31973bf9a127/libfdisk/src/libfdisk.h.in#L661-L697

```C
    /**
   * fdisk_labelitem_bsd:
   * @BSD_LABELITEM_TYPE: type
   * @BSD_LABELITEM_DISK: disk
   * @BSD_LABELITEM_PACKNAME: packname
   * @BSD_LABELITEM_FLAGS: flags (removable, ecc, badsect)
   * @BSD_LABELITEM_SECSIZE: Bytes/Sector
   * @BSD_LABELITEM_NTRACKS: Tracks/Cylinder
   * @BSD_LABELITEM_SECPERCYL: Sectors/Cylinder
   * @BSD_LABELITEM_CYLINDERS: Cylinders
   * @BSD_LABELITEM_RPM: rpm
   * @BSD_LABELITEM_INTERLEAVE: interleave
   * @BSD_LABELITEM_TRACKSKEW: trackskew
   * @BSD_LABELITEM_CYLINDERSKEW: cylinderskew
   * @BSD_LABELITEM_HEADSWITCH: headswitch
   * @BSD_LABELITEM_TRKSEEK: track-to-track seek
   *
   * BSD specific label items.
   */
  enum fdisk_labelitem_bsd {
    /* specific */
    BSD_LABELITEM_TYPE = __FDISK_NLABELITEMS,
    BSD_LABELITEM_DISK,
    BSD_LABELITEM_PACKNAME,
    BSD_LABELITEM_FLAGS,
    BSD_LABELITEM_SECSIZE,
    BSD_LABELITEM_NTRACKS,
    BSD_LABELITEM_SECPERCYL,
    BSD_LABELITEM_CYLINDERS,
    BSD_LABELITEM_RPM,
    BSD_LABELITEM_INTERLEAVE,
    BSD_LABELITEM_TRACKSKEW,
    BSD_LABELITEM_CYLINDERSKEW,
    BSD_LABELITEM_HEADSWITCH,
    BSD_LABELITEM_TRKSEEK
  };

```

https://github.com/util-linux/util-linux/blob/8aa25617467a1249669cff7240ca31973bf9a127/libfdisk/src/libfdisk.h.in#L704-L719

```C
    /**
   * fdisk_labelitem_sgi:
   * @SGI_LABELITEM_PCYLCOUNT: Physical cylinders
   * @SGI_LABELITEM_SPARECYL: Extra sects/cyl
   * @SGI_LABELITEM_ILFACT: nterleave
   * @SGI_LABELITEM_BOOTFILE: Bootfile
   *
   * SGI specific label items.
   */
  enum fdisk_labelitem_sgi {
    SGI_LABELITEM_PCYLCOUNT = __FDISK_NLABELITEMS,
    SGI_LABELITEM_SPARECYL,
    SGI_LABELITEM_ILFACT,
    SGI_LABELITEM_BOOTFILE
  };

```

https://github.com/util-linux/util-linux/blob/8aa25617467a1249669cff7240ca31973bf9a127/libfdisk/src/libfdisk.h.in#L775-L798

```C
    /**
   * fdisk_labelitem_gpt:
   * @GPT_LABELITEM_ID: GPT disklabel UUID (!= partition UUID)
   * @GPT_LABELITEM_FIRSTLBA: First Usable LBA
   * @GPT_LABELITEM_LASTLBA: Last Usable LBA
   * @GPT_LABELITEM_ALTLBA: Alternative LBA (backup header LBA)
   * @GPT_LABELITEM_ENTRIESLBA: Partitions entries array LBA
   * @GPT_LABELITEM_ENTRIESALLOC: Number of allocated entries in entries array
   * @GPT_LABELITEM_ENTRIESLASTLBA: Last LBA where is entries array
   *
   * GPT specific label items.
   */
  enum fdisk_labelitem_gpt {
    /* generic */
    GPT_LABELITEM_ID = FDISK_LABELITEM_ID,
    /* specific */
    GPT_LABELITEM_FIRSTLBA = __FDISK_NLABELITEMS,
    GPT_LABELITEM_LASTLBA,
    GPT_LABELITEM_ALTLBA,
    GPT_LABELITEM_ENTRIESLBA,
    GPT_LABELITEM_ENTRIESALLOC,
    GPT_LABELITEM_ENTRIESLASTLBA
  };

```


F3 - In the function `fdisk_locate_disklabel`, in what unit are `offset`, and
`size` expressed? bytes? sectors?

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libfdisk-docs/libfdisk-Label.html#fdisk-locate-disklabel

```text
  int
  fdisk_locate_disklabel (struct fdisk_context *cxt,
                          int n,
                          const char **name,
                          uint64_t *offset,
                          size_t *size);

  Locate disklabel and returns info about n item of the label.

  For example GPT is composed from three items, PMBR and GPT, n=0 return offset
  to PMBR and n=1 return offset to GPT Header and n=2 returns offset to GPT array
  of partitions, n=3 and n=4 returns location of the backup GPT label at the end
  of the disk.

  The function returns the current in-memory situation. It's possible that a
  header location is modified by write operation, for example when enabled
  minimization (see fdisk_gpt_enable_minimize()). In this case it's better to
  call this function after fdisk_write_disklabel().

  For more details see 'D' expert fdisk command.

  Parameters

    cxt context

    n N item

    name return item name

    offset return offset where is item

    size of the item

  Returns

    0 on success, <0 on error, 1 no more items.

```

## libmount

M1 - Does `libmount` plan to provide public functions to access/set the
private `fmt` field in `struct libmnt_table`?

From what I understand, `struct libmnt_table` is a generic data type used to
represent either of the following files:
- `/etc/fstab`
- `/proc/#/mountinfo`
- `/run/mount/utab`
- `/proc/swaps`

The `fmt` field helps distinguish each subtype, and being able to set it would
make it easier for me to instantiate the appropriate type Rust-side (i.e.
`FsTab`, `MountInfo`, `UTab`, `Swaps`).

https://github.com/util-linux/util-linux/blob/stable/v2.39/libmount/src/mountP.h#L252-L287

```C
/*
 * fstab/mountinfo file
 */
struct libmnt_table {
    int     fmt;        /* MNT_FMT_* file format */
    int     nents;      /* number of entries */
    int     refcount;   /* reference counter */
    int     comms;      /* enable/disable comment parsing */
    char        *comm_intro;    /* First comment in file */
    char        *comm_tail; /* Last comment in file */

    struct libmnt_cache *cache;     /* canonicalized paths/tags cache */

    int     (*errcb)(struct libmnt_table *tb,
             const char *filename, int line);

    int     (*fltrcb)(struct libmnt_fs *fs, void *data);
    void        *fltrcb_data;

    int     noautofs;   /* ignore autofs mounts */

    struct list_head    ents;   /* list of entries (libmnt_fs) */
    void        *userdata;
};

/*
 * Tab file format
 */
enum {
    MNT_FMT_GUESS,
    MNT_FMT_FSTAB,          /* /etc/{fs,m}tab */
    MNT_FMT_MTAB = MNT_FMT_FSTAB,   /* alias */
    MNT_FMT_MOUNTINFO,      /* /proc/#/mountinfo */
    MNT_FMT_UTAB,           /* /run/mount/utab */
    MNT_FMT_SWAPS           /* /proc/swaps */
};
```


M2 - If we were to split `struct libmnt_fs` into one type per file format,
would we get data types resembling `struct entry_fstab`, `struct
entry_mountinfo`, `struct entry_utab`, `struct_swaps` described below?

As far as I can tell, `struct libmnt_fs` is a multi-purpose data type
representing a line in either of the following files:
- `/etc/fstab`
- `/proc/#/mountinfo`
- `/run/mount/utab`
- `/proc/swaps`

Each file has a distinct format. So, some fields present in `struct libmnt_fs`
do not apply to certain files.

https://github.com/util-linux/util-linux/blob/stable/v2.39/libmount/src/mountP.h#L188-L239

```C
/*
 * This struct represents one entry in a fstab/mountinfo file.
 * (note that fstab[1] means the first column from fstab, and so on...)
 */
struct libmnt_fs {
    struct list_head ents;
    struct libmnt_table *tab;

    int     refcount;   /* reference counter */

    unsigned int    opts_age;   /* to sync with optlist */
    struct libmnt_optlist *optlist;

    int     id;     /* mountinfo[1]: ID */
    int     parent;     /* mountinfo[2]: parent */
    dev_t       devno;      /* mountinfo[3]: st_dev */

    char        *bindsrc;   /* utab, full path from fstab[1] for bind mounts */

    char        *source;    /* fstab[1], mountinfo[10], swaps[1]:
                                         * source dev, file, dir or TAG */
    char        *tagname;   /* fstab[1]: tag name - "LABEL", "UUID", ..*/
    char        *tagval;    /*           tag value */

    char        *root;      /* mountinfo[4]: root of the mount within the FS */
    char        *target;    /* mountinfo[5], fstab[2]: mountpoint */
    char        *fstype;    /* mountinfo[9], fstab[3]: filesystem type */

    char        *optstr;    /* fstab[4], merged options */
    char        *vfs_optstr;    /* mountinfo[6]: fs-independent (VFS) options */
    char        *opt_fields;    /* mountinfo[7]: optional fields */
    char        *fs_optstr; /* mountinfo[11]: fs-dependent options */
    char        *user_optstr;   /* userspace mount options */
    char        *attrs;     /* mount attributes */

    int     freq;       /* fstab[5]: dump frequency in days */
    int     passno;     /* fstab[6]: pass number on parallel fsck */

    /* /proc/swaps */
    char        *swaptype;  /* swaps[2]: device type (partition, file, ...) */
    off_t       size;       /* swaps[3]: swaparea size */
    off_t       usedsize;   /* swaps[4]: used size */
    int     priority;   /* swaps[5]: swap priority */

    int     flags;      /* MNT_FS_* flags */
    pid_t       tid;        /* /proc/<tid>/mountinfo otherwise zero */

    char        *comment;   /* fstab comment */

    void        *userdata;  /* library independent data */
};

```

### `/etc/fstab`

```C
struct entry_fstab {
    struct list_head ents;
    struct libmnt_table *tab;

    int     refcount;   /* reference counter */

    unsigned int    opts_age;   /* to sync with optlist */
    struct libmnt_optlist *optlist;


    char        *bindsrc;   /* utab, full path from fstab[1] for bind mounts */

    char        *source;    /* fstab[1], mountinfo[10], swaps[1]:
                                         * source dev, file, dir or TAG */
    char        *tagname;   /* fstab[1]: tag name - "LABEL", "UUID", ..*/
    char        *tagval;    /*           tag value */

    char        *target;    /* mountinfo[5], fstab[2]: mountpoint */
    char        *fstype;    /* mountinfo[9], fstab[3]: filesystem type */

    char        *optstr;    /* fstab[4], merged options */
    char        *user_optstr;   /* userspace mount options */
    char        *attrs;     /* mount attributes */

    int     freq;       /* fstab[5]: dump frequency in days */
    int     passno;     /* fstab[6]: pass number on parallel fsck */


    char        *comment;   /* fstab comment */

    void        *userdata;  /* library independent data */
};
```

### `/proc/#/mountinfo`

```C
struct entry_mountinfo {
    struct list_head ents;
    struct libmnt_table *tab;

    int     refcount;   /* reference counter */

    unsigned int    opts_age;   /* to sync with optlist */
    struct libmnt_optlist *optlist;

    int     id;     /* mountinfo[1]: ID */
    int     parent;     /* mountinfo[2]: parent */
    dev_t       devno;      /* mountinfo[3]: st_dev */

    char        *source;    /* fstab[1], mountinfo[10], swaps[1]:
                                         * source dev, file, dir or TAG */

    char        *root;      /* mountinfo[4]: root of the mount within the FS */
    char        *target;    /* mountinfo[5], fstab[2]: mountpoint */
    char        *fstype;    /* mountinfo[9], fstab[3]: filesystem type */

    char        *vfs_optstr;    /* mountinfo[6]: fs-independent (VFS) options */
    char        *opt_fields;    /* mountinfo[7]: optional fields */
    char        *fs_optstr; /* mountinfo[11]: fs-dependent options */
    char        *user_optstr;   /* userspace mount options */

    pid_t       tid;        /* /proc/<tid>/mountinfo otherwise zero */
};
```

### `/run/mount/utab`

```C
struct entry_utab {
    struct list_head ents;
    struct libmnt_table *tab;

    int     refcount;   /* reference counter */

    unsigned int    opts_age;   /* to sync with optlist */
    struct libmnt_optlist *optlist;

    int     id;     /* mountinfo[1]: ID */
    int     parent;     /* mountinfo[2]: parent */
    dev_t       devno;      /* mountinfo[3]: st_dev */

    char        *bindsrc;   /* utab, full path from fstab[1] for bind mounts */

    char        *source;    /* fstab[1], mountinfo[10], swaps[1]:
                                         * source dev, file, dir or TAG */

    char        *root;      /* mountinfo[4]: root of the mount within the FS */
    char        *target;    /* mountinfo[5], fstab[2]: mountpoint */

    char        *user_optstr;   /* userspace mount options */
    char        *attrs;     /* mount attributes */

    void        *userdata;  /* library independent data */
};
```

### `/proc/swaps`

```C
struct entry_swaps {
    struct list_head ents;
    struct libmnt_table *tab;

    int     refcount;   /* reference counter */

    unsigned int    opts_age;   /* to sync with optlist */
    struct libmnt_optlist *optlist;


    char        *source;    /* fstab[1], mountinfo[10], swaps[1]:
                                         * source dev, file, dir or TAG */

    /* /proc/swaps */
    char        *swaptype;  /* swaps[2]: device type (partition, file, ...) */
    off_t       size;       /* swaps[3]: swaparea size */
    off_t       usedsize;   /* swaps[4]: used size */
    int     priority;   /* swaps[5]: swap priority */

};
```


M3 - About `struct libmnt_fs` mentioned in question `M2`, is the following a
good partition of which subsets of functions, acting on the struct, are
specific/exclusive to each type of file entry?  (We assume that items not in
a union of the subsets below are shared between line types)

### Functions specific/exclusive to `/etc/fstab`

- `mnt_fs_append_comment`
- `mnt_fs_append_options `
- `mnt_fs_get_comment `
- `mnt_fs_get_freq `
- `mnt_fs_get_fstype `
- `mnt_fs_get_option `
- `mnt_fs_get_options `
- `mnt_fs_get_passno `
- `mnt_fs_get_source `
- `mnt_fs_get_tag `
- `mnt_fs_get_target `
- `mnt_fs_match_fstype `
- `mnt_fs_match_options `
- `mnt_fs_match_target `
- `mnt_fs_prepend_options `
- `mnt_fs_print_debug `
- `mnt_fs_set_comment `
- `mnt_fs_set_freq `
- `mnt_fs_set_fstype `
- `mnt_fs_set_options `
- `mnt_fs_set_passno `
- `mnt_fs_set_source `
- `mnt_fs_set_target `
- `mnt_fs_streq_target `
- `mnt_fs_to_mntent `
- `mnt_new_fs `

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-append-comment

```text
int
mnt_fs_append_comment (struct libmnt_fs *fs,
                       const char *comm);

See also mnt_fs_set_comment().
Parameters

fs fstab entry pointer

comm comment string

Returns

0 on success or <0 in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-append-options

```text
int
mnt_fs_append_options (struct libmnt_fs *fs,
                       const char *optstr);

Parses (splits) optstr and appends results to VFS, FS and userspace lists of options.

If optstr is NULL, then fs is not modified and 0 is returned.
Parameters

fs fstab/mtab/mountinfo entry

optstr mount options

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-comment

```text
const char *
mnt_fs_get_comment (struct libmnt_fs *fs);

Parameters

fs fstab/mtab/mountinfo entry pointer

Returns

0 on success, 1 when not found the name or negative number in case of error.

```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-freq

```text
int
mnt_fs_get_freq (struct libmnt_fs *fs);

Parameters

fs fstab/mtab/mountinfo entry pointer

Returns

dump frequency in days.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-fstype

```text
const char *
mnt_fs_get_fstype (struct libmnt_fs *fs);

Parameters

fs fstab/mtab/mountinfo entry pointer

Returns

pointer to filesystem type.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-option

```text
int
mnt_fs_get_option (struct libmnt_fs *fs,
                   const char *name,
                   char **value,
                   size_t *valsz);

Parameters

fs fstab/mtab/mountinfo entry pointer

name option name

value returns pointer to the beginning of the value (e.g. name=VALUE) or NULL

valsz returns size of options value or 0

Returns

0 on success, 1 when name not found or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-options

```text
const char *
mnt_fs_get_options (struct libmnt_fs *fs);

Parameters

fs fstab/mtab/mountinfo entry pointer

Returns

pointer to string or NULL in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-passno

```text
int
mnt_fs_get_passno (struct libmnt_fs *fs);

Parameters

fs fstab/mtab entry pointer

Returns

"pass number on parallel fsck".
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-source

```text
const char *
mnt_fs_get_source (struct libmnt_fs *fs);

Parameters

fs struct libmnt_file (fstab/mtab/mountinfo) fs

Returns

mount source. Note that the source could be unparsed TAG (LABEL/UUID). See also mnt_fs_get_srcpath() and mnt_fs_get_tag().
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-tag

```text
int
mnt_fs_get_tag (struct libmnt_fs *fs,
                const char **name,
                const char **value);

"TAG" is NAME=VALUE (e.g. LABEL=foo)

The TAG is the first column in the fstab file. The TAG or "srcpath" always has to be set for all entries.

See also mnt_fs_get_source().

char *src;
struct libmnt_fs *fs = mnt_table_find_target(tb, "/home", MNT_ITER_FORWARD);

if (!fs)
goto err;

src = mnt_fs_get_srcpath(fs);
if (!src) {
char *tag, *val;
if (mnt_fs_get_tag(fs, &tag, &val) == 0)
printf("%s: %s\n", tag, val); // LABEL or UUID
} else
printf("device: %s\n", src); // device or bind path

Parameters

fs fs

name returns pointer to NAME string

value returns pointer to VALUE string

Returns

0 on success or negative number in case a TAG is not defined.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-target

```text
const char *
mnt_fs_get_target (struct libmnt_fs *fs);

Parameters

fs fstab/mtab/mountinfo entry pointer

Returns

pointer to mountpoint path or NULL
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-match-fstype

```text
int
mnt_fs_match_fstype (struct libmnt_fs *fs,
                     const char *types);

For more details see mnt_match_fstype().
Parameters

fs filesystem

types filesystem name or comma delimited list of filesystems

Returns

1 if fs type is matching to types , else 0. The function returns 0 when types is NULL.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-match-options

```text
int
mnt_fs_match_options (struct libmnt_fs *fs,
                      const char *options);

For more details see mnt_match_options().
Parameters

fs filesystem

options comma delimited list of options (and nooptions)

Returns

1 if fs type is matching to options , else 0. The function returns 0 when types is NULL.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-match-target

```text
int
mnt_fs_match_target (struct libmnt_fs *fs,
                     const char *target,
                     struct libmnt_cache *cache);

Possible are three attempts: 1) compare target with fs->target

2) realpath(target ) with fs->target

3) realpath(target ) with realpath(fs->target ) if fs is not from /proc/self/mountinfo.

However, if mnt_cache_set_targets(cache, mtab) was called, and the path target or fs->target is found in the mtab , the canonicalization is is not performed (see mnt_resolve_target()).

The 2nd and 3rd attempts are not performed when cache is NULL.
Parameters

fs filesystem

target mountpoint path

cache tags/paths cache or NULL

Returns

1 if fs target is equal to target , else 0.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-prepend-options

```text
int
mnt_fs_prepend_options (struct libmnt_fs *fs,
                        const char *optstr);

Parses (splits) optstr and prepends the results to VFS, FS and userspace lists of options.

If optstr is NULL, then fs is not modified and 0 is returned.
Parameters

fs fstab/mtab/mountinfo entry

optstr mount options

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-print-debug

```text
int
mnt_fs_print_debug (struct libmnt_fs *fs,
                    FILE *file);

Parameters

fs fstab/mtab/mountinfo entry

file file stream

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-comment

```text
int
mnt_fs_set_comment (struct libmnt_fs *fs,
                    const char *comm);

Note that the comment has to be terminated by '\n' (new line), otherwise the whole filesystem entry will be written as a comment to the tabfile (e.g. fstab).
Parameters

fs fstab entry pointer

comm comment string

Returns

0 on success or <0 in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-freq

```text
int
mnt_fs_set_freq (struct libmnt_fs *fs,
                 int freq);

Parameters

fs fstab/mtab entry pointer

freq dump frequency in days

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-fstype

```text
int
mnt_fs_set_fstype (struct libmnt_fs *fs,
                   const char *fstype);

This function creates a private copy (strdup()) of fstype .
Parameters

fs fstab/mtab/mountinfo entry

fstype filesystem type

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-options

```text
int
mnt_fs_set_options (struct libmnt_fs *fs,
                    const char *optstr);

Splits optstr to VFS, FS and userspace mount options and updates relevant parts of fs .
Parameters

fs fstab/mtab/mountinfo entry pointer

optstr options string

Returns

0 on success, or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-passno


```text
int
mnt_fs_set_passno (struct libmnt_fs *fs,
                   int passno);

Parameters

fs fstab/mtab entry pointer

passno pass number

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-source

```text
int
mnt_fs_set_source (struct libmnt_fs *fs,
                   const char *source);

This function creates a private copy (strdup()) of source .
Parameters

fs fstab/mtab/mountinfo entry

source new source

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-target

```text
int
mnt_fs_set_target (struct libmnt_fs *fs,
                   const char *tgt);

This function creates a private copy (strdup()) of tgt .
Parameters

fs fstab/mtab/mountinfo entry

tgt mountpoint

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-streq-target

```text
int
mnt_fs_streq_target (struct libmnt_fs *fs,
                     const char *path);

Compares fs target path with path . The redundant slashes are ignored. This
function compares strings and does not canonicalize the paths. See also more
generic mnt_fs_match_target().

Parameters

fs fs

path mount point

Returns

1 if fs target path equal to path , otherwise 0.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-to-mntent

```text
int
mnt_fs_to_mntent (struct libmnt_fs *fs,
                  struct mntent **mnt);

Copies the information from fs to struct mntent mnt . If mnt is already set,
then the struct mntent items are reallocated and updated. See also
mnt_free_mntent().

Parameters

fs filesystem

mnt mount description (as described in mntent.h)

Returns

0 on success and a negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-new-fs

```text
struct libmnt_fs *
mnt_new_fs (void);

The initial refcount is 1, and needs to be decremented to release the resources of the filesystem.
Returns

newly allocated struct libmnt_fs.
```

### Functions specific/exclusive to `/proc/#/mountinfo`

- `mnt_fs_get_devno `
- `mnt_fs_get_fs_options `
- `mnt_fs_get_fstype `
- `mnt_fs_get_id `
- `mnt_fs_get_optional_fields `
- `mnt_fs_get_parent_id `
- `mnt_fs_get_propagation `
- `mnt_fs_get_root `
- `mnt_fs_get_target `
- `mnt_fs_get_tid `
- `mnt_fs_get_vfs_options `
- `mnt_fs_get_vfs_options_all `
- `mnt_fs_match_fstype `
- `mnt_fs_match_target `
- `mnt_fs_print_debug `
- `mnt_fs_strdup_options `
- `mnt_fs_streq_target `

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-devno

```text
dev_t
mnt_fs_get_devno (struct libmnt_fs *fs);

Parameters

fs /proc/self/mountinfo entry

Returns

value of st_dev for files on filesystem or 0 in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-fs-options

```text
const char *
mnt_fs_get_fs_options (struct libmnt_fs *fs);

Parameters

fs fstab/mtab/mountinfo entry pointer

Returns

pointer to superblock (fs-depend) mount option string or NULL.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-fstype

```text
const char *
mnt_fs_get_fstype (struct libmnt_fs *fs);

Parameters

fs fstab/mtab/mountinfo entry pointer

Returns

pointer to filesystem type.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-id

```text
int
mnt_fs_get_id (struct libmnt_fs *fs);

Parameters

fs /proc/self/mountinfo entry

Returns

mount ID (unique identifier of the mount) or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-optional-fields

```text
const char *
mnt_fs_get_optional_fields (struct libmnt_fs *fs);

Parameters

fs mountinfo entry pointer

Returns

pointer to string with mountinfo optional fields or NULL in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-parent-id

```text
int
mnt_fs_get_parent_id (struct libmnt_fs *fs);

Parameters

fs /proc/self/mountinfo entry

Returns

parent mount ID or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-propagation

```text
int
mnt_fs_get_propagation (struct libmnt_fs *fs,
                        unsigned long *flags);

Note that this function sets flags to zero if no propagation flags are found in
the mountinfo file. The kernel default is MS_PRIVATE, this flag is not stored
in the mountinfo file.

Parameters

fs mountinfo entry

flags returns propagation MS_* flags as present in the mountinfo file

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-root

```text
const char *
mnt_fs_get_root (struct libmnt_fs *fs);

Parameters

fs /proc/self/mountinfo entry

Returns

root of the mount within the filesystem or NULL
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-target

```text
const char *
mnt_fs_get_target (struct libmnt_fs *fs);

Parameters

fs fstab/mtab/mountinfo entry pointer

Returns

pointer to mountpoint path or NULL
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-tid

```text
pid_t
mnt_fs_get_tid (struct libmnt_fs *fs);

Parameters

fs /proc/tid/mountinfo entry

Returns

TID (task ID) for filesystems read from the mountinfo file
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-vfs-options

```text
const char *
mnt_fs_get_vfs_options (struct libmnt_fs *fs);

Parameters

fs fstab/mtab entry pointer

Returns

pointer to fs-independent (VFS) mount option string or NULL.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-vfs-options-all

```text
char *
mnt_fs_get_vfs_options_all (struct libmnt_fs *fs);

Parameters

fs fstab/mtab entry pointer

Returns

pointer to newlly allocated string (can be freed by free(3)) or NULL in case of
error. The string contains all (including defaults) mount options.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-match-fstype

```text
int
mnt_fs_match_fstype (struct libmnt_fs *fs,
                     const char *types);

For more details see mnt_match_fstype().
Parameters

fs filesystem

types filesystem name or comma delimited list of filesystems

Returns

1 if fs type is matching to types , else 0. The function returns 0 when types is NULL.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-match-target

```text
int
mnt_fs_match_target (struct libmnt_fs *fs,
                     const char *target,
                     struct libmnt_cache *cache);

Possible are three attempts: 1) compare target with fs->target

2) realpath(target ) with fs->target

3) realpath(target ) with realpath(fs->target ) if fs is not from /proc/self/mountinfo.

However, if mnt_cache_set_targets(cache, mtab) was called, and the path target
or fs->target is found in the mtab , the canonicalization is is not performed
(see mnt_resolve_target()).

The 2nd and 3rd attempts are not performed when cache is NULL.
Parameters

fs filesystem

target mountpoint path

cache tags/paths cache or NULL

Returns

1 if fs target is equal to target , else 0.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-print-debug

```text
int
mnt_fs_print_debug (struct libmnt_fs *fs,
                    FILE *file);

Parameters

fs fstab/mtab/mountinfo entry

file file stream

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-strdup-options

```text
char *
mnt_fs_strdup_options (struct libmnt_fs *fs);

Merges all mount options (VFS, FS and userspace) to one options string and
returns the result. This function does not modify fs .

Parameters

fs


fstab/mtab/mountinfo entry pointer

Returns

pointer to string (can be freed by free(3)) or NULL in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-streq-target

```text
int
mnt_fs_streq_target (struct libmnt_fs *fs,
                     const char *path);

Compares fs target path with path . The redundant slashes are ignored. This
function compares strings and does not canonicalize the paths. See also more
generic mnt_fs_match_target().

Parameters

fs fs

path mount point

Returns

1 if fs target path equal to path , otherwise 0.
```

### Functions specific/exclusive to `/run/mount/utab`

- `mnt_fs_append_attributes `
- `mnt_fs_get_attribute `
- `mnt_fs_get_attributes `
- `mnt_fs_get_bindsrc `
- `mnt_fs_get_id `
- `mnt_fs_get_root `
- `mnt_fs_get_user_options `
- `mnt_fs_match_options `
- `mnt_fs_match_target `
- `mnt_fs_prepend_attributes `
- `mnt_fs_set_attributes `
- `mnt_fs_set_bindsrc `
- `mnt_fs_set_root `
- `mnt_fs_set_source `
- `mnt_fs_streq_target `

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-append-attributes

```text
int
mnt_fs_append_attributes (struct libmnt_fs *fs,
                          const char *optstr);

Appends mount attributes. (See mnt_fs_set_attributes()).

Parameters

fs fstab/mtab/mountinfo entry

optstr options string

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-attribute

```text
int
mnt_fs_get_attribute (struct libmnt_fs *fs,
                      const char *name,
                      char **value,
                      size_t *valsz);

Parameters

fs fstab/mtab/mountinfo entry pointer

name option name

value returns pointer to the beginning of the value (e.g. name=VALUE) or NULL

valsz returns size of options value or 0

Returns

0 on success, 1 when name not found or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-attributes

```text
const char *
mnt_fs_get_attributes (struct libmnt_fs *fs);

Parameters

fs fstab/mtab entry pointer

Returns

pointer to attributes string or NULL.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-bindsrc

```text
const char *
mnt_fs_get_bindsrc (struct libmnt_fs *fs);

Parameters

fs /run/mount/utab entry

Returns

full path that was used for mount(2) on MS_BIND
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-id

```text
int
mnt_fs_get_id (struct libmnt_fs *fs);

Parameters

fs /proc/self/mountinfo entry

Returns

mount ID (unique identifier of the mount) or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-root

```text
const char *
mnt_fs_get_root (struct libmnt_fs *fs);

Parameters

fs /proc/self/mountinfo entry

Returns

root of the mount within the filesystem or NULL
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-user-options

```text
const char *
mnt_fs_get_user_options (struct libmnt_fs *fs);

Parameters

fs fstab/mtab entry pointer

Returns

pointer to userspace mount option string or NULL.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-match-options

```text
int
mnt_fs_match_options (struct libmnt_fs *fs,
                      const char *options);

For more details see mnt_match_options().
Parameters

fs filesystem

options comma delimited list of options (and nooptions)

Returns

1 if fs type is matching to options , else 0. The function returns 0 when types is NULL.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-match-target

```text
int
mnt_fs_match_target (struct libmnt_fs *fs,
                     const char *target,
                     struct libmnt_cache *cache);

Possible are three attempts: 1) compare target with fs->target

2) realpath(target ) with fs->target

3) realpath(target ) with realpath(fs->target ) if fs is not from /proc/self/mountinfo.

However, if mnt_cache_set_targets(cache, mtab) was called, and the path target
or fs->target is found in the mtab , the canonicalization is is not performed
(see mnt_resolve_target()).

The 2nd and 3rd attempts are not performed when cache is NULL.

Parameters

fs filesystem

target mountpoint path

cache tags/paths cache or NULL

Returns

1 if fs target is equal to target , else 0.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-prepend-attributes

```text
int
mnt_fs_prepend_attributes (struct libmnt_fs *fs,
                           const char *optstr);

Prepends mount attributes. (See mnt_fs_set_attributes()).

Parameters

fs fstab/mtab/mountinfo entry

optstr options string

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-attributes

```text
int
mnt_fs_set_attributes (struct libmnt_fs *fs,
                       const char *optstr);

Sets mount attributes. The attributes are mount(2) and mount(8) independent
options, these options are not sent to the kernel and are not interpreted by
libmount. The attributes are stored in /run/mount/utab only.

The attributes are managed by libmount in userspace only. It's possible that
information stored in userspace will not be available for libmount after
CLONE_FS unshare. Be careful, and don't use attributes if possible.

Parameters

fs fstab/mtab/mountinfo entry

optstr options string

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-bindsrc

```text
int
mnt_fs_set_bindsrc (struct libmnt_fs *fs,
                    const char *src);

Parameters

fs filesystem

src path

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-root

```text
int
mnt_fs_set_root (struct libmnt_fs *fs,
                 const char *path);

Parameters

fs mountinfo entry

path root path

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-source

```text
int
mnt_fs_set_source (struct libmnt_fs *fs,
                   const char *source);

This function creates a private copy (strdup()) of source .

Parameters

fs fstab/mtab/mountinfo entry

source new source

Returns

0 on success or negative number in case of error.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-streq-target

```text
int
mnt_fs_streq_target (struct libmnt_fs *fs,
                     const char *path);

Compares fs target path with path . The redundant slashes are ignored. This
function compares strings and does not canonicalize the paths. See also more
generic mnt_fs_match_target().

Parameters

fs fs

path mount point

Returns

1 if fs target path equal to path , otherwise 0.
```

### Functions specific/exclusive to `/proc/swaps`

- `mnt_fs_get_priority `
- `mnt_fs_get_size `
- `mnt_fs_get_swaptype `
- `mnt_fs_get_usedsize `
- `mnt_fs_set_priority `

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-priority

```text
int
mnt_fs_get_priority (struct libmnt_fs *fs);

Parameters

fs /proc/swaps entry

Returns

priority
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-size

```text
off_t
mnt_fs_get_size (struct libmnt_fs *fs);

Parameters

fs /proc/swaps entry

Returns

size
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-swaptype

```text
const char *
mnt_fs_get_swaptype (struct libmnt_fs *fs);

Parameters

fs /proc/swaps entry

Returns

swap type or NULL
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-get-usedsize

```text
off_t
mnt_fs_get_usedsize (struct libmnt_fs *fs);

Parameters

fs /proc/swaps entry

Returns

used size

```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-priority

```text
int
mnt_fs_set_priority (struct libmnt_fs *fs,
                     int prio);

Parameters

fs /proc/swaps entry


prio priority

Returns

0 or -1 in case of error

Since: 2.28
```


M4 - What role does the `userdata` field in `libmnt_fs` play? For which file
entry is it necessary? `fstab`, `mountinfo`, `utab`, `swaps`?

https://github.com/util-linux/util-linux/blob/8aa25617467a1249669cff7240ca31973bf9a127/libmount/src/mountP.h#L237

```C
void *userdata; /* library independent data */
```


M5 - Could anyone provide more information about the format used by the entries
in `/run/mount/utab`? Are the definitions reproduced below correct?

By reading the code for the `mnt_parse_utab_line` function, I identified the
following keys for possible key-value pairs in `/run/mount/utab`.

A cursory search on the web yielded these definitions:
- `SRC`: the mounted device,
- `TARGET`: the device’s mount point,
- `ROOT`: ??
- `BINDSRC`: the source of a bind mount,
- `OPTS`: mount options,
- `ATTRS`: options independent from those used by the mount syscall and mount
  command. They are neither sent to the kernel, nor interpreted by libmount. They
  are stored in /run/mount/utab, and managed by libmount in userspace only.

https://github.com/util-linux/util-linux/blob/8aa25617467a1249669cff7240ca31973bf9a127/libmount/src/tab_parse.c#L326-L368

```C
if (!fs->id && !strncmp(p, "ID=", 3)) {
int rc = 0;


end = next_s32(p + 3, &fs->id, &rc);
if (!end || rc)
return rc;


} else if (!fs->source && !strncmp(p, "SRC=", 4)) {
char *v = unmangle(p + 4, &end);
if (!v)
goto enomem;
if (__mnt_fs_set_source_ptr(fs, v))
free(v);


} else if (!fs->target && !strncmp(p, "TARGET=", 7)) {
fs->target = unmangle(p + 7, &end);
if (!fs->target)
goto enomem;


} else if (!fs->root && !strncmp(p, "ROOT=", 5)) {
fs->root = unmangle(p + 5, &end);
if (!fs->root)
goto enomem;


} else if (!fs->bindsrc && !strncmp(p, "BINDSRC=", 8)) {
fs->bindsrc = unmangle(p + 8, &end);
if (!fs->bindsrc)
goto enomem;


} else if (!fs->user_optstr && !strncmp(p, "OPTS=", 5)) {
fs->user_optstr = unmangle(p + 5, &end);
if (!fs->user_optstr)
goto enomem;


} else if (!fs->attrs && !strncmp(p, "ATTRS=", 6)) {
fs->attrs = unmangle(p + 6, &end);
if (!fs->attrs)
goto enomem;


} else {
/* unknown variable */
while (*p && *p != ' ') p++;
}
```


M6 - Can the `SRC` key mentioned in question `M5` have a:
- tag (UUID, PARTUUID, LABEL, etc.)
- network ID (Samba: `smb://ip-address-or-hostname/shared-dir`, SSHFS:
  `user@ip-address-or-hostname:/shared-dir`, etc.)
 as value? (e.g. SRC="UUID=ac4f36bf-191b-4fb0-b808-6d7fc9fc88be")


M7 - What does `mnt_fs_set_root` do? Is it meant for `/proc/self/mountinfo`,
`/run/mount/utab`, or both?

Although `libmnt_fs` can represent a line in `/proc/self/mountinfo`, files in
`/proc` are usually read-only, managed directly by the Linux kernel.

However, the docstring of `mnt_fs_set_root` says that it is supposed to modify
an entry in `/proc/self/mountinfo`.

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-root

```text
int
mnt_fs_set_root (struct libmnt_fs *fs,
                 const char *path);

Parameters

    fs mountinfo entry
    path root path

Returns

  0 on success or negative number in case of error.

```


M8 - What is `mnt_context_apply_fstab` supposed to do?

The documentation only says "This function is optional".

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Library-high-level-context.html#mnt-context-apply-fstab

```text
int
mnt_context_apply_fstab (struct libmnt_context *cxt);

This function is optional.

Parameters

  cxt mount context

Returns

  0 on success, negative number in case of error.
```


M9 - Why does `mnt_optstr_prepend_option("", "ro", "recursive")` return
`"ro=recursive,"`, but `mnt_optstr_append_option("", "ro", "recursive")` return
`"ro=recursive"`? What is the extra comma after the keyword `recursive` output
by `mnt_optstr_prepend_option` for?

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Options-string.html#mnt-optstr-prepend-option

```text
int
mnt_optstr_prepend_option (char **optstr,
                           const char *name,
                           const char *value);

Parameters

optstr option string or NULL, returns a reallocated string

name value name

value value

Returns

0 on success or <0 in case of error. After an error the optstr should be unmodified.
```

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Options-string.html#mnt-optstr-append-option

```text
int
mnt_optstr_append_option (char **optstr,
                          const char *name,
                          const char *value);

Parameters

optstr option string or NULL, returns a reallocated string

name value name

value value

Returns

0 on success or <0 in case of error. After an error the optstr should be unmodified.
```


M10 - In option maps, what does using the mask `MNT_INVERT` do to mountflags
(e.g. `noatime`, `suid`, others)?

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Option-maps.html#MNT-INVERT:CAPS

```text
#define MNT_INVERT (1 << 1) /* invert the mountflag */
```


M11 - Which definition is correct, or am I conflating two notions?

The function `mnt_fs_set_freq` sets the backup frequency (in days) of a drive in
`/etc/fstab`. According to `libmount`, it takes an integer value.

But, from [An introduction to the Linux /etc/fstab
file](https://www.redhat.com/en/blog/etc-fstab) the value in the fifth column
on each line` in `/etc/fstab` can only take two values, `0 = no backup` or `1 =
dump utility backup of a partition`.



> Backup Operation: (the first digit) this is a binary system where 1 = dump
> utility backup of a partition. 0 = no backup. This is an outdated backup
> method and should NOT be used.

https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.39/libmount-docs/libmount-Filesystem.html#mnt-fs-set-freq

```text
int
mnt_fs_set_freq (struct libmnt_fs *fs,
                 int freq);

Parameters

fs fstab/mtab entry pointer

freq dump frequency in days

Returns

0 on success or negative number in case of error.
```

Thank you for reading this far. Please accept my apologies for making you go
through this wall of text m(__)m

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Questions about util-linux
  2025-06-05 10:25 Questions about util-linux Nick Piaddo
@ 2025-06-08 21:37 ` Thomas Weißschuh
  0 siblings, 0 replies; 2+ messages in thread
From: Thomas Weißschuh @ 2025-06-08 21:37 UTC (permalink / raw)
  To: Nick Piaddo; +Cc: util-linux@vger.kernel.org

On 2025-06-05 10:25:07+0000, Nick Piaddo wrote:
> **As my first post on this mailing list, please advise if "this is NOT the way..."**
> 
> Hi,
> 
> I am developing a personal project in Rust for which I need to probe block
> devices, create, and mount partitions; `libblkid`, `libfdisk`, and `libmount`
> fit the bill perfectly.

So you want to use the original C libraries and wrap them from rust,
correct? Not reimplement them.

These libraries are LGPL. Your crates, for which are asking about
internal details are licensed as Apache or MIT, which looks iffy.
Especially if the libraries are then linked statically.
Best stick to the LGPL.

> So, I am writing Rust bindings for `util-linux-2.39` (published on `crates.io`):
> - `rsblkid`: [crate](https://crates.io/crates/rsblkid)  [docs](https://docs.rs/rsblkid/latest/rsblkid/)
> - `rsfdisk`: [crate](https://crates.io/crates/rsfdisk)  [docs](https://docs.rs/rsfdisk/latest/rsfdisk/)
> - `rsmount`: [crate](https://crates.io/crates/rsmount)  [docs](https://docs.rs/rsmount/latest/rsmount/)
> 
> They are first drafts with APIs that are still in flux, with low test coverage,
> and some C functions are still missing their Rust equivalents.
> 
> Even after going through:
> - the source code of each C library,
> - their documentation pages,
> - the manpages of `blkid`,  `fdisk`, `mount`,

Also look at libblkid(3)

> - and searching the net for as much information as I could find,
> 
> the docs of each crate still reflects my limited knowledge of `util-linux`.
> 
> So, I do have a few questions I hope experts on this list may be able to
> answer (see further down). **Warning:** It's a long read!

These are a lot of questions. I'll respond to the ones I have
answers to. The amount most likely reduces your chances to get
responses.
If these questions were generated automatically please mention it.

> Nick
> 
> ## How are questions structured?
> 
> Most questions follow the pattern described below:

<snip>

> Please mention the ID of the question you are answering, or are seeking
> clarifications for. It will make the conversation easier to follow.

I will reply inline. Right below the question.
This will keep the context very celar.

> Thanks! (^-^)b
> 
> ## General questions
> 
> G1 - Would it be possible to provide a way to define a destructor for functions
> registering callbacks, long-lived or otherwise?
> 
> Interoperating with C, and registering callback functions requires Rust to
> allocate state data on the heap.
> 
> From the [Rustonomicon](https://doc.rust-lang.org/nomicon/ffi.html#destructors)
> we learn that:
> > Foreign libraries often hand off ownership of resources to the calling code.
> > When this occurs, we must use Rust's destructors to provide safety and
> > guarantee the release of these resources (especially in the case of panic).
> 
> To free dynamically allocated Rust data, C functions registering callbacks
> should have a signature like the one shown below:
> 
> ```C
> void widget_register_callback(
>     widget_t *widget,
>     void *data,
>     void (*callback)(void*, event_t),
>     void (*destroy)(void*)
> );
> ```
> 
> See this blog post [Neat Rust Tricks: Passing Rust Closures to
> C](http://blog.sagetheprogrammer.com/neat-rust-tricks-passing-rust-closures-to-c)
> for a presentation of what I dream `util-linux` had. (╥﹏╥)つ
> 
> While reading `util-linux`'s source code, I identified three types of functions
> to register callbacks:
> 
> - functions for which it is essentially impossible to create Rust bindings,
>   case in point: `fdisk_table_sort_partitions` (see documentation further down).
>   This function has a signature that looks like the example below.

This should only be true for closures. If you use a regular function with
static lifetime fdisk_table_sort_partitions() should work fine.
A closure does not make sense here anyways.

> - functions for registering long-lived callbacks with a signature like the one
>   shown below
> 
>   ```C
>   void widget_register_callback(
>       widget_t *widget,
>       void (*callback)(void*, event_t),
>   );
>   ```
>   For example, `mnt_table_set_parser_errcb` that acts on a `struct
>   libmnt_table`. This structure has an internal field to store a data pointer,
>   along with specialized accessor functions to get/set it (respectively
>   `mnt_table_get_userdata `, and `mnt_table_set_userdata `). However, lacking a
>   way to define a destructor, this function will leak memory each time it is
>   called to replace a callback.

The mnt_table is owned by your rust code. So the rust code can clean up
the userdata together with the mnt_table.

> - functions for registering short-lived callbacks with a signature like the one
>   shown below
> 
>   ```C
>   void widget_register_callback(
>       widget_t *widget,
>       void *data,
>       void (*callback)(void*, event_t),
>   );
>   ```
>   For example, `mnt_table_find_next_fs` which is the closest to the ideal form.
>   Although it lacks a way to define a destructor, being short-lived, it allows
>   the enclosing Rust binding to take care of releasing resources allocated on
>   the heap.

Here the data should be owned by the function calling
mnt_table_find_next_fs() and it will be cleaned up nicely when the
function returns.

> 
> https://github.com/util-linux/util-linux/blob/stable/v2.39/libfdisk/src/fdiskP.h#L200-L205

Why use v2.39 and not the latest versions?
Some of your problems may already be resolved there.

<snip a lot of blablabla>

> G2 - How can I create device images that will trigger errors when running
> unit-tests?

<blabla>

> Knowing how to create an intentionally broken device image would be wonderful.
> It would allow me to increase test coverage of my Rust-bindings.

This question does not make sense. It's not the responsibility of your
code to look at the raw image file.
util-linux is fuzzed with random input as part of oss-fuzz.

> ## libblkid
> 
> B1 - Are there public accessor functions on the roadmap of `libblkid` for
> reading the private fields `bid_pri`, `bid_devno`, and `bid_time` in
> `blkid_dev_struct`?
> 
> For the moment, I can not accurately reproduce the way data about a
> `blkid_struct_dev` is printed in `/run/blkid/blkid.tab` due to not being able
> to access the relevant fields.

blkid.tab is an internal file. Why do you need to reproduce it?

<snip>

> B2 - Does anyone know what the function `blkid_dev_set_search` is supposed to
> do?
> 
> There are no docstrings for this function. Although I read its source code, I
> could not figure out its purpose.  <('^-^)
> 
> https://github.com/util-linux/util-linux/blob/stable/v2.39/libblkid/src/dev.c#L150-L172

Seems quite obvious to me. It allows you to search for files with a
certain tag value.

<snip the code>

Why is all this pointless code in the email?
If somebody is not capable of looking up the code they won't be able to
help anyways.

> B3 -  Do I define `size` as `uint64_t` or `int64_t`?
> 
> The `size` field in `struct blkid_struct_probe` is of type `uint64_t`. But,
> according to the documentation, its accessor function `blkid_probe_get_sectors`
> may return `-1` in case of error.

`struct blkid_struct_probe` is internal. The types it uses are of no
concern to your code. Stick to the public interface.

> Reading the code of `blkid_probe_get_sectors`, I can see that it just divides
> `size` by 512 which would never return a negative value (see below).

If the function is documented as being able to return an error, then
write your code with this consideration.

<snip>

> B4 - Is the documentation out-of-date or just anticipating a future change?
> 
> The function `blkid_probe_set_sectorsize` always returns `0`, but its docstring
> says otherwise.

The docstring defines the interface, trust it.

<snip>

> B5 - Is there a list of all file systems supported by `libblkid`?

> By searching the source code, I managed to constitute a list of supported file
> systems gathered in the enum
> [`FileSystem`](https://docs.rs/rsblkid/latest/rsblkid/partition/enum.FileSystem.html#variants)
> in `rsblkid`.
> 
> It would be nice if I could double-check its accuracy from an official
> reference.

blkid --list-filesystems

This is documented.

> B6 - Is there a list of all tags supported by `libblkid`?
> 
> By searching the source code, I managed to constitute a list of supported tags
> gathered in the enum
> [`Tag`](https://docs.rs/rsblkid/latest/rsblkid/device/enum.Tag.html#variants)
> in `rsblkid`.
> 
> It would be nice if I could double-check its accuracy from an official
> reference.

This is documented in libblkid(3).
I wouldn't represent this as enum, though.

<snip>

> ## libmount
> 
> M1 - Does `libmount` plan to provide public functions to access/set the
> private `fmt` field in `struct libmnt_table`?
> 
> From what I understand, `struct libmnt_table` is a generic data type used to
> represent either of the following files:
> - `/etc/fstab`
> - `/proc/#/mountinfo`
> - `/run/mount/utab`
> - `/proc/swaps`
> 
> The `fmt` field helps distinguish each subtype, and being able to set it would
> make it easier for me to instantiate the appropriate type Rust-side (i.e.
> `FsTab`, `MountInfo`, `UTab`, `Swaps`).

Why do you need this?

<snip>

> M2 - If we were to split `struct libmnt_fs` into one type per file format,
> would we get data types resembling `struct entry_fstab`, `struct
> entry_mountinfo`, `struct entry_utab`, `struct_swaps` described below?
> 
> As far as I can tell, `struct libmnt_fs` is a multi-purpose data type
> representing a line in either of the following files:
> - `/etc/fstab`
> - `/proc/#/mountinfo`
> - `/run/mount/utab`
> - `/proc/swaps`
> 
> Each file has a distinct format. So, some fields present in `struct libmnt_fs`
> do not apply to certain files.

All of this is private implementation why do you need it?

<snip>

> M3 - About `struct libmnt_fs` mentioned in question `M2`, is the following a
> good partition of which subsets of functions, acting on the struct, are
> specific/exclusive to each type of file entry?  (We assume that items not in
> a union of the subsets below are shared between line types)
> 
> ### Functions specific/exclusive to `/etc/fstab`
> 
> - `mnt_fs_append_comment`
> - `mnt_fs_append_options `
> - `mnt_fs_get_comment `
> - `mnt_fs_get_freq `
> - `mnt_fs_get_fstype `
> - `mnt_fs_get_option `
> - `mnt_fs_get_options `
> - `mnt_fs_get_passno `
> - `mnt_fs_get_source `
> - `mnt_fs_get_tag `
> - `mnt_fs_get_target `
> - `mnt_fs_match_fstype `
> - `mnt_fs_match_options `
> - `mnt_fs_match_target `
> - `mnt_fs_prepend_options `
> - `mnt_fs_print_debug `
> - `mnt_fs_set_comment `
> - `mnt_fs_set_freq `
> - `mnt_fs_set_fstype `
> - `mnt_fs_set_options `
> - `mnt_fs_set_passno `
> - `mnt_fs_set_source `
> - `mnt_fs_set_target `
> - `mnt_fs_streq_target `
> - `mnt_fs_to_mntent `
> - `mnt_new_fs `

This question does not make sense.

> ### Functions specific/exclusive to `/proc/#/mountinfo`
> 
> - `mnt_fs_get_devno `
> - `mnt_fs_get_fs_options `
> - `mnt_fs_get_fstype `
> - `mnt_fs_get_id `
> - `mnt_fs_get_optional_fields `
> - `mnt_fs_get_parent_id `
> - `mnt_fs_get_propagation `
> - `mnt_fs_get_root `
> - `mnt_fs_get_target `
> - `mnt_fs_get_tid `
> - `mnt_fs_get_vfs_options `
> - `mnt_fs_get_vfs_options_all `
> - `mnt_fs_match_fstype `
> - `mnt_fs_match_target `
> - `mnt_fs_print_debug `
> - `mnt_fs_strdup_options `
> - `mnt_fs_streq_target `

This list also does not make sense.

> ### Functions specific/exclusive to `/run/mount/utab`
> 
> - `mnt_fs_append_attributes `
> - `mnt_fs_get_attribute `
> - `mnt_fs_get_attributes `
> - `mnt_fs_get_bindsrc `
> - `mnt_fs_get_id `
> - `mnt_fs_get_root `
> - `mnt_fs_get_user_options `
> - `mnt_fs_match_options `
> - `mnt_fs_match_target `
> - `mnt_fs_prepend_attributes `
> - `mnt_fs_set_attributes `
> - `mnt_fs_set_bindsrc `
> - `mnt_fs_set_root `
> - `mnt_fs_set_source `
> - `mnt_fs_streq_target `

Why is for example `mnt_fs_print_debug` missing?
This looks random.
Don't try to "improve" the API. It will break at some point.

<snip>

> M5 - Could anyone provide more information about the format used by the entries
> in `/run/mount/utab`? Are the definitions reproduced below correct?
> 
> By reading the code for the `mnt_parse_utab_line` function, I identified the
> following keys for possible key-value pairs in `/run/mount/utab`.

Why? It is a private implementation detail.

<snip>

> M6 - Can the `SRC` key mentioned in question `M5` have a:
> - tag (UUID, PARTUUID, LABEL, etc.)
> - network ID (Samba: `smb://ip-address-or-hostname/shared-dir`, SSHFS:
>   `user@ip-address-or-hostname:/shared-dir`, etc.)
>  as value? (e.g. SRC="UUID=ac4f36bf-191b-4fb0-b808-6d7fc9fc88be")

Still a private implementation detail.

> M7 - What does `mnt_fs_set_root` do? Is it meant for `/proc/self/mountinfo`,
> `/run/mount/utab`, or both?
> 
> Although `libmnt_fs` can represent a line in `/proc/self/mountinfo`, files in
> `/proc` are usually read-only, managed directly by the Linux kernel.
> 
> However, the docstring of `mnt_fs_set_root` says that it is supposed to modify
> an entry in `/proc/self/mountinfo`.

It modifies the entry in memory.

> M8 - What is `mnt_context_apply_fstab` supposed to do?

Looks to me like it extends the context with information found in
/etc/fstab.

<snip>

> Thank you for reading this far. Please accept my apologies for making you go
> through this wall of text m(__)m

Please don't quote all this code.


Thomas

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-06-08 21:47 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-05 10:25 Questions about util-linux Nick Piaddo
2025-06-08 21:37 ` Thomas Weißschuh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).