mirror of
https://github.com/microsoft/WSL.git
synced 2025-12-10 00:44:55 -06:00
* link: Collect WSL logs (recommended method) Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: Advanced Authoring Tests in C++ Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: CMake Documentation and Community Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: Collect WSL logs for networking issues Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: Collect WSL logs (recommended method) Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: ; otherwise, Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: a Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: access Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: accessible Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: across Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: actively Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: adapters Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: address Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: addresses Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: and Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: appropriate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: argument Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: associated Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: attach Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: available Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: beginning Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: between Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: binaries Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: bound Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: buffer Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: buffers Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: cannot Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: canonical Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: capabilities Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: case-insensitive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: case-sensitive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: certified Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: command Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: committer Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: communication Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: complains Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: configuration Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: consumed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: continue Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: converted Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: currently Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: customers Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: daemon Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: deferred Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: definitions Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: delimiter Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: delivered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: dellink Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: derived Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: descriptor Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destined Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destruct Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destructible Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destructor Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: detach Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: differentiate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: directories Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: disassociate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: disposition Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: distribution Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: distro Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: duping Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: emitted Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: empty Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: environment Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: every time Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: exclusive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: expected Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: expire Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: explicitly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: fall back Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: false Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: fastfail Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: filesystem Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: first Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: followed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: for Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: functionality Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: functionally Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: github Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: greater Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: guarantee Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: guaranteed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: handles Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hangup Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hierarchy Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hogwarts Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hydrated Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: icrnl Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: implementation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: implementing Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: initialize Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: instance Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: instantiate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: instantiations Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: intentionally Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: interpret Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: interpreter Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: irreversibly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: iteration Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: iterator Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: its Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: kernel Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: kmsg Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: knowledge Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: maximum Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: mirrored Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: msftconnecttest Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: multi Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: multiple Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: mutable Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: namespace Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: nonexistent Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: notifications Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: occurred Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: occurring Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: otherwise, Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: outstanding Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: overridden Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: partition Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: pass through Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: passthrough Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: performs Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: periodically Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: positional Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: precedence Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: preexisting Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: preferring Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: prepopulate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: previous Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: privileges Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: process Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: processes Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: programmatically Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: protection Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: provided Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: reasonable Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: receive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: received Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: red hat Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: reentrant Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: registered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: regularly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: relay Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: release Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: representing Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: requests Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: response Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: resurrect Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: retention Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: returned Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: security Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: semaphore Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: separate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: separator Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: service Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: set up Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: setup Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: severely Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: should Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: signal Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: similarly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: simple Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: simplified Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: single Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: specified Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: splitting Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: standard Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: stress Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: succeed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: success Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: successfully Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: supplementary Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: synced Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: system Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: take Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: than Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: that opening Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: the Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: threadpool Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: to Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: true Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: truncate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: tunneling Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unexpected Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: uninitialize Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unique Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unprivileged Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unregistered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: untrusted Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: upgrade Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: utility Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: validating Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: variant Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: variation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: variations Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: verify Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: visible Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: whether Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: winget Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: worker Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: written Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: wslservice Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * format source --------- Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> Co-authored-by: Ben Hillis <benhillis@gmail.com> Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
853 lines
18 KiB
C
853 lines
18 KiB
C
/*++
|
|
|
|
Copyright (c) Microsoft. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
lxtmount.c
|
|
|
|
Abstract:
|
|
|
|
This file contains mount primitive support.
|
|
|
|
--*/
|
|
|
|
#include "lxtlog.h"
|
|
#include <sys/mman.h>
|
|
#include "lxtcommon.h"
|
|
#include <sys/mount.h>
|
|
#include <linux/capability.h>
|
|
#include <sys/sysmacros.h>
|
|
#include <libgen.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <libmount/libmount.h>
|
|
#include <sys/mman.h>
|
|
#include "lxtmount.h"
|
|
|
|
#define PATH_MAX (4096)
|
|
|
|
void MountEscapeString(const char* Source, char* Dest, size_t Length);
|
|
|
|
int MountCheckIsMount(
|
|
const char* Path,
|
|
int ExpectedParentId,
|
|
const char* ExpectedSource,
|
|
const char* ExpectedFsType,
|
|
const char* ExpectedRoot,
|
|
const char* ExpectedMountOptions,
|
|
const char* ExpectedFsOptions,
|
|
const char* ExpectedCombinedOptions,
|
|
int Flags)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine checks if a path is a mount point.
|
|
|
|
Arguments:
|
|
|
|
Args - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
Returns the mount ID on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
int Direction;
|
|
const char* ExpectedSourceActual;
|
|
struct libmnt_fs* FileSystem;
|
|
char LocalPath[PATH_MAX];
|
|
int MountId;
|
|
int Result;
|
|
struct stat Stat;
|
|
struct libmnt_table* Table;
|
|
|
|
Table = NULL;
|
|
if (strcmp(Path, "/") != 0)
|
|
{
|
|
LxtCheckResult(MountIsMount(AT_FDCWD, Path));
|
|
if (Result == 0)
|
|
{
|
|
LxtLogError("%s is not a mount point.", Path);
|
|
Result = LXT_RESULT_FAILURE;
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
LxtCheckErrnoZeroSuccess(stat(Path, &Stat));
|
|
|
|
//
|
|
// Verify the mount in the /proc/self/mountinfo file.
|
|
//
|
|
|
|
if ((Flags & MOUNT_FIRST_MOUNT) != 0)
|
|
{
|
|
Direction = MNT_ITER_FORWARD;
|
|
}
|
|
else
|
|
{
|
|
Direction = MNT_ITER_BACKWARD;
|
|
}
|
|
|
|
LxtCheckResult(MountFindMount(MOUNT_PROC_MOUNTINFO, Path, 0, &Table, &FileSystem, Direction));
|
|
|
|
LxtCheckNotEqual(FileSystem, NULL, "%p");
|
|
LxtLogInfo("%s on %s fstype %s (%s)", mnt_fs_get_source(FileSystem), mnt_fs_get_target(FileSystem), mnt_fs_get_fstype(FileSystem), mnt_fs_get_options(FileSystem));
|
|
|
|
ExpectedSourceActual = ExpectedSource;
|
|
|
|
#if LIBMOUNT_MAJOR_VERSION >= 2
|
|
|
|
if ((ExpectedSourceActual == NULL) && (strcmp(ExpectedFsType, "virtiofs") != 0))
|
|
{
|
|
ExpectedSourceActual = "none";
|
|
}
|
|
|
|
#endif
|
|
|
|
LxtCheckEqual(ExpectedParentId, mnt_fs_get_parent_id(FileSystem), "%d");
|
|
if (ExpectedSourceActual)
|
|
{
|
|
LxtCheckStringEqual(ExpectedSourceActual, mnt_fs_get_source(FileSystem));
|
|
}
|
|
|
|
LxtCheckStringEqual(ExpectedFsType, mnt_fs_get_fstype(FileSystem));
|
|
strcpy(LocalPath, ExpectedRoot);
|
|
if ((Flags & MOUNT_SOURCE_DELETED) != 0)
|
|
{
|
|
strcat(LocalPath, "//deleted");
|
|
}
|
|
|
|
LxtCheckStringEqual(LocalPath, mnt_fs_get_root(FileSystem));
|
|
LxtCheckStringEqual(ExpectedMountOptions, mnt_fs_get_vfs_options(FileSystem));
|
|
if (ExpectedFsOptions != NULL)
|
|
{
|
|
LxtCheckStringEqual(ExpectedFsOptions, mnt_fs_get_fs_options(FileSystem));
|
|
}
|
|
|
|
LxtCheckEqual(Stat.st_dev, mnt_fs_get_devno(FileSystem), "%lu");
|
|
MountId = mnt_fs_get_id(FileSystem);
|
|
LxtCheckGreater(MountId, 0, "%d");
|
|
LxtCheckNotEqual(MountId, ExpectedParentId, "%d");
|
|
mnt_free_table(Table);
|
|
Table = NULL;
|
|
|
|
//
|
|
// Verify the mount in the /proc/mounts file.
|
|
//
|
|
|
|
LxtCheckResult(MountFindMount(MOUNT_PROC_MOUNTS, Path, 0, &Table, &FileSystem, Direction));
|
|
|
|
LxtCheckNotEqual(FileSystem, NULL, "%p");
|
|
if (ExpectedSourceActual)
|
|
{
|
|
LxtCheckStringEqual(ExpectedSourceActual, mnt_fs_get_source(FileSystem));
|
|
}
|
|
|
|
LxtCheckStringEqual(ExpectedFsType, mnt_fs_get_fstype(FileSystem));
|
|
if (ExpectedCombinedOptions != NULL)
|
|
{
|
|
LxtCheckStringEqual(ExpectedCombinedOptions, mnt_fs_get_options(FileSystem));
|
|
}
|
|
|
|
//
|
|
// Verify the mount in the /proc/self/mountstats file.
|
|
//
|
|
|
|
if (ExpectedSourceActual)
|
|
{
|
|
LxtCheckResult(MountFindMountStats(ExpectedSource, Path, ExpectedFsType));
|
|
}
|
|
|
|
Result = MountId;
|
|
|
|
ErrorExit:
|
|
if (Table != NULL)
|
|
{
|
|
mnt_free_table(Table);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int MountCheckIsNotMount(const char* Path)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine checks if a path is a mount point.
|
|
|
|
Arguments:
|
|
|
|
Args - Supplies the command line arguments.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
struct libmnt_fs* FileSystem;
|
|
int Result;
|
|
struct libmnt_table* Table;
|
|
|
|
Table = NULL;
|
|
LxtCheckResult(MountIsMount(AT_FDCWD, Path));
|
|
if (Result != 0)
|
|
{
|
|
LxtLogError("%s is a mount point.", Path);
|
|
Result = LXT_RESULT_FAILURE;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Verify the mount is not in the /proc/self/mountinfo file.
|
|
//
|
|
|
|
LxtCheckResult(MountFindMount(MOUNT_PROC_MOUNTINFO, Path, 0, &Table, &FileSystem, MNT_ITER_BACKWARD));
|
|
|
|
LxtCheckEqual(FileSystem, NULL, "%p");
|
|
mnt_free_table(Table);
|
|
Table = NULL;
|
|
|
|
//
|
|
// Verify the mount in the /proc/mounts file.
|
|
//
|
|
|
|
LxtCheckResult(MountFindMount(MOUNT_PROC_MOUNTS, Path, 0, &Table, &FileSystem, MNT_ITER_BACKWARD));
|
|
|
|
LxtCheckEqual(FileSystem, NULL, "%p");
|
|
|
|
ErrorExit:
|
|
if (Table != NULL)
|
|
{
|
|
mnt_free_table(Table);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
void MountEscapeString(const char* Source, char* Dest, size_t Length)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine escapes a string using procfs rules.
|
|
|
|
Arguments:
|
|
|
|
Source - Supplies the string to escape.
|
|
|
|
Dest - Supplies the buffer to write the escaped string to.
|
|
|
|
Length - Supplies the length of the destination buffer.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
size_t Index;
|
|
|
|
for (Index = 0; (Index < Length - 1) && (*Source != '\0'); Index += 1, Source += 1)
|
|
{
|
|
switch (*Source)
|
|
{
|
|
case ' ':
|
|
case '\n':
|
|
case '\t':
|
|
case '\\':
|
|
Index += snprintf(Dest + Index, Length - Index, "\\%03o", *Source) - 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
Dest[Index] = *Source;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Dest[Index] = '\0';
|
|
return;
|
|
}
|
|
|
|
int MountFindMount(const char* MountsFile, const char* MountPoint, dev_t Device, struct libmnt_table** Table, struct libmnt_fs** FileSystem, int Direction)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine finds a mount in the specified file by either mount point
|
|
or device.
|
|
|
|
Arguments:
|
|
|
|
MountsFile - Supplies the file to use (e.g. /proc/self/mountinfo).
|
|
|
|
MountPoint - Supplies the mount point to search for. If NULL, device is
|
|
used instead.
|
|
|
|
Device - Supplies the device to search for if mount point is NULL.
|
|
|
|
Table - Supplies a pointer that receives the parsed table. The caller
|
|
must use mnt_free_table to free the table.
|
|
|
|
FileSystem - Supplies a pointer that receives the file system, or NULL
|
|
if none was found.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
struct libmnt_iter* Iterator;
|
|
struct libmnt_fs* LocalFileSystem;
|
|
struct libmnt_table* LocalTable;
|
|
int Result;
|
|
|
|
LocalFileSystem = NULL;
|
|
Iterator = NULL;
|
|
LocalTable = mnt_new_table_from_file(MountsFile);
|
|
LxtCheckNotEqual(LocalTable, NULL, "%p");
|
|
|
|
//
|
|
// A backwards iterator is used to find the most recent mount.
|
|
//
|
|
|
|
if (MountPoint != NULL)
|
|
{
|
|
*FileSystem = mnt_table_find_target(LocalTable, MountPoint, Direction);
|
|
}
|
|
else
|
|
{
|
|
*FileSystem = NULL;
|
|
Iterator = mnt_new_iter(MNT_ITER_FORWARD);
|
|
LxtCheckNotEqual(Iterator, NULL, "%p");
|
|
while (mnt_table_next_fs(LocalTable, Iterator, &LocalFileSystem) == 0)
|
|
{
|
|
if (mnt_fs_get_devno(LocalFileSystem) == Device)
|
|
{
|
|
*FileSystem = LocalFileSystem;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return the table so the memory for file system remains valid.
|
|
//
|
|
|
|
if (*FileSystem != NULL)
|
|
{
|
|
*Table = LocalTable;
|
|
LocalTable = NULL;
|
|
}
|
|
|
|
Result = 0;
|
|
|
|
ErrorExit:
|
|
if (Iterator != NULL)
|
|
{
|
|
mnt_free_iter(Iterator);
|
|
}
|
|
|
|
if (LocalTable != NULL)
|
|
{
|
|
mnt_free_table(LocalTable);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int MountFindMountStats(const char* Device, const char* MountPoint, const char* FsType)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine finds a mount with the specified options in the
|
|
/proc/self/mountstats file.
|
|
|
|
N.B. libmount does not support parsing the mountstats file so this is done
|
|
manually.
|
|
|
|
Arguments:
|
|
|
|
Device - Supplies the mount source.
|
|
|
|
MountPoint - Supplies the mount point.
|
|
|
|
FsType - Supplies the file system type.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
char EscapedDevice[100];
|
|
char EscapedMountPoint[100];
|
|
char ExpectedLine[256];
|
|
int Result;
|
|
|
|
//
|
|
// Format the expected mountstats line.
|
|
//
|
|
|
|
MountEscapeString(MountPoint, EscapedMountPoint, LXT_COUNT_OF(EscapedMountPoint));
|
|
if (Device == NULL)
|
|
{
|
|
snprintf(ExpectedLine, sizeof(ExpectedLine), "no device mounted on %s with fstype %s", EscapedMountPoint, FsType);
|
|
}
|
|
else
|
|
{
|
|
MountEscapeString(Device, EscapedDevice, LXT_COUNT_OF(EscapedDevice));
|
|
snprintf(ExpectedLine, sizeof(ExpectedLine), "device %s mounted on %s with fstype %s", EscapedDevice, EscapedMountPoint, FsType);
|
|
}
|
|
|
|
LxtCheckResult(MountFindMountStatsLine(ExpectedLine));
|
|
|
|
ErrorExit:
|
|
return Result;
|
|
}
|
|
|
|
int MountFindMountStatsLine(char* ExpectedLine)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine checks if a specific line exists in the mountstats file.
|
|
|
|
Arguments:
|
|
|
|
ExpectedLine - Supplies the line to find.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
bool Found;
|
|
FILE* File;
|
|
char Line[256];
|
|
int Result;
|
|
|
|
File = fopen(MOUNT_PROC_MOUNTSTATS, "r");
|
|
LxtCheckNotEqual(File, NULL, "%p");
|
|
Found = FALSE;
|
|
while (feof(File) == 0)
|
|
{
|
|
if (fgets(Line, sizeof(Line), File) == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Strip the trailing \n and compare.
|
|
//
|
|
|
|
Line[strlen(Line) - 1] = '\0';
|
|
if (strncmp(ExpectedLine, Line, sizeof(Line)) == 0)
|
|
{
|
|
Found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Found == false)
|
|
{
|
|
LxtLogError("'%s' not found in " MOUNT_PROC_MOUNTSTATS, ExpectedLine);
|
|
Result = LXT_RESULT_FAILURE;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
Result = LXT_RESULT_SUCCESS;
|
|
|
|
ErrorExit:
|
|
if (File != NULL)
|
|
{
|
|
fclose(File);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int MountGetMountId(const char* Path)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine gets the mount ID for the specified path.
|
|
|
|
Arguments:
|
|
|
|
Path - Supplies the path. Does not have to be a mount point.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
struct libmnt_fs* FileSystem;
|
|
int Result;
|
|
struct stat Stat;
|
|
struct libmnt_table* Table;
|
|
|
|
//
|
|
// Find the mount ID of the directory. This is done by device because
|
|
// it may not be a mount point.
|
|
//
|
|
|
|
FileSystem = NULL;
|
|
Table = NULL;
|
|
LxtCheckErrnoZeroSuccess(stat(Path, &Stat));
|
|
LxtCheckResult(MountFindMount(MOUNT_PROC_MOUNTINFO, NULL, Stat.st_dev, &Table, &FileSystem, MNT_ITER_BACKWARD));
|
|
|
|
LxtCheckNotEqual(FileSystem, NULL, "%p");
|
|
Result = mnt_fs_get_id(FileSystem);
|
|
|
|
ErrorExit:
|
|
if (Table != NULL)
|
|
{
|
|
mnt_free_table(Table);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int MountGetFileSystem(const char* Path, char* FsType, int FsTypeLength, char* Options, int OptionsLength)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine gets the file system type of the mount containing the
|
|
specified path.
|
|
|
|
Arguments:
|
|
|
|
Path - Supplies the path.
|
|
|
|
FsType - Supplies a buffer that receives the name of the file system type.
|
|
|
|
Length - Supplies the size of the buffer.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
struct libmnt_fs* FileSystem;
|
|
const char* LocalFsType;
|
|
const char* LocalOptions;
|
|
int Result;
|
|
struct stat Stat;
|
|
struct libmnt_table* Table;
|
|
|
|
//
|
|
// Find the mount ID of the directory. This is done by device because
|
|
// it may not be a mount point.
|
|
//
|
|
|
|
FileSystem = NULL;
|
|
Table = NULL;
|
|
LxtCheckErrnoZeroSuccess(stat(Path, &Stat));
|
|
LxtCheckResult(MountFindMount(MOUNT_PROC_MOUNTINFO, NULL, Stat.st_dev, &Table, &FileSystem, MNT_ITER_BACKWARD));
|
|
|
|
LxtCheckNotEqual(FileSystem, NULL, "%p");
|
|
LocalFsType = mnt_fs_get_fstype(FileSystem);
|
|
LocalOptions = mnt_fs_get_options(FileSystem);
|
|
LxtLogInfo("File system at %s uses fstype %s, options %s.", Path, LocalFsType, LocalOptions);
|
|
|
|
if (strlen(LocalFsType) >= FsTypeLength)
|
|
{
|
|
LxtLogError("Buffer too small for file system name");
|
|
Result = LXT_RESULT_FAILURE;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if (strlen(LocalOptions) >= OptionsLength)
|
|
{
|
|
LxtLogError("Buffer too small for options.");
|
|
Result = LXT_RESULT_FAILURE;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
strcpy(FsType, LocalFsType);
|
|
strcpy(Options, LocalOptions);
|
|
|
|
ErrorExit:
|
|
if (Table != NULL)
|
|
{
|
|
mnt_free_table(Table);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int MountGetMountOptions(const char* Path, char* Options)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine gets mount options, which generally describe the mount peer
|
|
group information for the specified path.
|
|
|
|
Arguments:
|
|
|
|
Path - Supplies the path. Does not have to be a mount point.
|
|
|
|
Options - Supplies a string buffer to receive the options
|
|
|
|
Return Value:
|
|
|
|
Returns 0 on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
struct libmnt_fs* FileSystem;
|
|
const char* LocalOptions;
|
|
int Result;
|
|
struct libmnt_table* Table;
|
|
|
|
//
|
|
// Find the mount ID of the directory.
|
|
//
|
|
|
|
FileSystem = NULL;
|
|
Table = NULL;
|
|
LxtCheckResult(MountFindMount(MOUNT_PROC_MOUNTINFO, Path, 0, &Table, &FileSystem, MNT_ITER_BACKWARD));
|
|
|
|
//
|
|
// shared:X, master:X, propagate_from:X, unbindable
|
|
//
|
|
|
|
LocalOptions = mnt_fs_get_optional_fields(FileSystem);
|
|
if (LocalOptions != NULL)
|
|
{
|
|
strcpy(Options, LocalOptions);
|
|
}
|
|
else
|
|
{
|
|
Options[0] = '\0';
|
|
}
|
|
|
|
ErrorExit:
|
|
if (Table != NULL)
|
|
{
|
|
mnt_free_table(Table);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int MountIsFileSystem(const char* Path, const char* FsType)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine checks the file system type of the mount containing the
|
|
specified path.
|
|
|
|
Arguments:
|
|
|
|
Path - Supplies the path.
|
|
|
|
FsType - Supplies the name of the file system type.
|
|
|
|
Return Value:
|
|
|
|
Returns 1 if the path uses the specified file system, 0 if not, and -1 on
|
|
failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
const char* ActualFsType;
|
|
struct libmnt_fs* FileSystem;
|
|
int Result;
|
|
struct stat Stat;
|
|
struct libmnt_table* Table;
|
|
|
|
//
|
|
// Find the mount ID of the directory. This is done by device because
|
|
// it may not be a mount point.
|
|
//
|
|
|
|
FileSystem = NULL;
|
|
Table = NULL;
|
|
LxtCheckErrnoZeroSuccess(stat(Path, &Stat));
|
|
LxtCheckResult(MountFindMount(MOUNT_PROC_MOUNTINFO, NULL, Stat.st_dev, &Table, &FileSystem, MNT_ITER_BACKWARD));
|
|
|
|
LxtCheckNotEqual(FileSystem, NULL, "%p");
|
|
ActualFsType = mnt_fs_get_fstype(FileSystem);
|
|
LxtLogInfo("File system at %s uses fstype %s.", Path, ActualFsType);
|
|
if (strcmp(ActualFsType, FsType) == 0)
|
|
{
|
|
Result = 1;
|
|
}
|
|
else
|
|
{
|
|
Result = 0;
|
|
}
|
|
|
|
ErrorExit:
|
|
if (Table != NULL)
|
|
{
|
|
mnt_free_table(Table);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
int MountIsMount(int DirFd, const char* Path)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine checks if a path is a mount point.
|
|
|
|
Arguments:
|
|
|
|
Fd - Supplies the file descriptor to start resolving the path.
|
|
|
|
Path - Supplies the path.
|
|
|
|
Return Value:
|
|
|
|
Returns 0 if the path is not a mount point, 1 if it is a mount point, or
|
|
-1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
char LocalPath[PATH_MAX];
|
|
char* ParentPath;
|
|
struct stat ParentStat;
|
|
int Result;
|
|
struct stat Stat;
|
|
|
|
LxtCheckErrnoZeroSuccess(fstatat(DirFd, Path, &Stat, AT_SYMLINK_NOFOLLOW));
|
|
strncpy(LocalPath, Path, sizeof(LocalPath) - 1);
|
|
ParentPath = dirname(LocalPath);
|
|
LxtCheckErrnoZeroSuccess(fstatat(DirFd, ParentPath, &ParentStat, AT_SYMLINK_NOFOLLOW));
|
|
|
|
LxtLogInfo(
|
|
"%s device: %u,%u; %s device: %u,%u", ParentPath, major(ParentStat.st_dev), minor(ParentStat.st_dev), Path, major(Stat.st_dev), minor(Stat.st_dev));
|
|
|
|
if (Stat.st_dev == ParentStat.st_dev)
|
|
{
|
|
Result = 0;
|
|
}
|
|
else
|
|
{
|
|
Result = 1;
|
|
}
|
|
|
|
ErrorExit:
|
|
return Result;
|
|
}
|
|
|
|
int MountPrepareTmpfs(char* Path, char* Device, int ExpectedParentId)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine creates a tmpfs mount for testing.
|
|
|
|
Arguments:
|
|
|
|
Path - Supplies the mount point path.
|
|
|
|
Device - Supplies the device name to use.
|
|
|
|
ExpectedParentId - Supplies the expected parent mount ID.
|
|
|
|
Return Value:
|
|
|
|
Returns the mount ID on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
return MountPrepareTmpfsEx(Path, Device, ExpectedParentId, 0, "rw,relatime");
|
|
}
|
|
|
|
int MountPrepareTmpfsEx(char* Path, char* Device, int ExpectedParentId, int Flags, const char* ExpectedOptions)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine creates a tmpfs mount for testing.
|
|
|
|
Arguments:
|
|
|
|
Path - Supplies the mount point path.
|
|
|
|
Device - Supplies the device name to use.
|
|
|
|
ExpectedParentId - Supplies the expected parent mount ID.
|
|
|
|
Flags - Supplies the mount flags.
|
|
|
|
ExpectedOptions - Supplies the expected mount option string.
|
|
|
|
Return Value:
|
|
|
|
Returns the mount ID on success, -1 on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
int MountId;
|
|
int Result;
|
|
|
|
LxtCheckErrnoZeroSuccess(mkdir(Path, 0700));
|
|
LxtCheckErrnoZeroSuccess(mount(Device, Path, "tmpfs", Flags, NULL));
|
|
LxtCheckResult(MountId = MountCheckIsMount(Path, ExpectedParentId, Device, "tmpfs", "/", ExpectedOptions, "rw", ExpectedOptions, 0));
|
|
|
|
Result = MountId;
|
|
|
|
ErrorExit:
|
|
return Result;
|
|
}
|