Questions about util-linux
Nick Piaddo <[email protected]>
| Newsgroups | org.kernel.vger.util-linux |
|---|---|
| Message-ID | <IM79iX-yrSm2eLiLvGaZqJbIZaqT9SuLnpz0GuSvYOizxuYCJucKrIfwPYCjCos13Y4njHyPz3ftnmz6y5MrsTr6plHxqBIHUDF59iH-GlA=@protonmail.com> |
**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