mirror of
https://github.com/microsoft/WSL.git
synced 2025-07-03 07:23:20 +00:00

Many Microsoft employees have contributed to the Windows Subsystem for Linux, this commit is the result of their work since 2016. The entire history of the Windows Subsystem for Linux can't be shared here, but here's an overview of WSL's history after it moved to it own repository in 2021: Number of commits on the main branch: 2930 Number of contributors: 31 Head over https://github.com/microsoft/WSL/releases for a more detailed history of the features added to WSL since 2021.
852 lines
18 KiB
C
852 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 sytem 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 sytem 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;
|
|
}
|