blob: 7572411ddb7e4aebbf1060a4a81e7a78cbd08cd3 [file] [log] [blame] [edit]
/* Test using the fsinfo() system call to query mount parameters.
*
* Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#define _GNU_SOURCE
#define _ATFILE_SOURCE
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <math.h>
#include <sys/syscall.h>
#include <linux/fsinfo.h>
#include <linux/fcntl.h>
#include <sys/stat.h>
#ifndef __NR_fsopen
#define __NR_fsopen -1
#endif
#ifndef __NR_fsinfo
#define __NR_fsinfo -1
#endif
static int fsopen(const char *fs_name, unsigned int flags)
{
return syscall(__NR_fsopen, fs_name, flags);
}
static ssize_t fsinfo(int dfd, const char *filename, struct fsinfo_params *params,
void *buffer, size_t buf_size)
{
return syscall(__NR_fsinfo, dfd, filename, params, buffer, buf_size);
}
static const char *param_types[NR__FSINFO_PARAM_SPEC] = {
[FSINFO_PARAM_SPEC_NOT_DEFINED] = "?undef",
[FSINFO_PARAM_SPEC_IS_FLAG] = "flag",
[FSINFO_PARAM_SPEC_IS_BOOL] = "bool",
[FSINFO_PARAM_SPEC_IS_U32] = "u32",
[FSINFO_PARAM_SPEC_IS_U32_OCTAL] = "octal",
[FSINFO_PARAM_SPEC_IS_U32_HEX] = "hex",
[FSINFO_PARAM_SPEC_IS_S32] = "s32",
[FSINFO_PARAM_SPEC_IS_U64] = "u64",
[FSINFO_PARAM_SPEC_IS_ENUM] = "enum",
[FSINFO_PARAM_SPEC_IS_STRING] = "string",
[FSINFO_PARAM_SPEC_IS_BLOB] = "binary",
[FSINFO_PARAM_SPEC_IS_BLOCKDEV] = "blockdev",
[FSINFO_PARAM_SPEC_IS_PATH] = "path",
[FSINFO_PARAM_SPEC_IS_FD] = "fd",
};
/*
*
*/
int main(int argc, char **argv)
{
struct fsinfo_param_description desc;
struct fsinfo_param_specification spec;
struct fsinfo_param_enum enum_name;
struct fsinfo_params params = {
.at_flags = AT_FSINFO_FROM_FSOPEN,
};
int fd;
if (argc != 2) {
printf("Format: test-fs-query <fs_name>\n");
exit(2);
}
fd = fsopen(argv[1], 0);
if (fd == -1) {
perror(argv[1]);
exit(1);
}
params.request = FSINFO_ATTR_PARAM_DESCRIPTION;
if (fsinfo(fd, NULL, &params, &desc, sizeof(desc)) == -1) {
perror("fsinfo/desc");
exit(1);
}
printf("Filesystem %s has %u parameters\n", argv[1], desc.nr_params);
params.request = FSINFO_ATTR_PARAM_SPECIFICATION;
for (params.Nth = 0; params.Nth < desc.nr_params; params.Nth++) {
char type[32];
if (fsinfo(fd, NULL, &params, &spec, sizeof(spec)) == -1) {
if (errno == ENODATA)
break;
perror("fsinfo/spec");
exit(1);
}
if (spec.type < NR__FSINFO_PARAM_SPEC)
strcpy(type, param_types[spec.type]);
else
sprintf(type, "?%u", spec.type);
printf("- PARAM[%3u] %-20s %3u %s%s%s%s%s\n",
params.Nth,
spec.name,
spec.opt,
type,
spec.flags & FSINFO_PARAM_SPEC_VALUE_IS_OPTIONAL ? ",opt" : "",
spec.flags & FSINFO_PARAM_SPEC_PREFIX_NO_IS_NEG ? ",neg-no" : "",
spec.flags & FSINFO_PARAM_SPEC_EMPTY_STRING_IS_NEG ? ",neg-empty" : "",
spec.flags & FSINFO_PARAM_SPEC_DEPRECATED ? ",dep" : "");
}
printf("Filesystem has %u enumeration values\n", desc.nr_enum_names);
params.request = FSINFO_ATTR_PARAM_ENUM;
for (params.Nth = 0; params.Nth < desc.nr_enum_names; params.Nth++) {
if (fsinfo(fd, NULL, &params, &enum_name, sizeof(enum_name)) == -1) {
if (errno == ENODATA)
break;
perror("fsinfo/enum");
exit(1);
}
printf("- ENUM[%3u] %3u: %s\n",
params.Nth, enum_name.opt, enum_name.name);
}
return 0;
}