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

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).