mirror of
https://github.com/libfuse/libfuse.git
synced 2026-07-07 14:47:41 +08:00
a32cec008c
Examples help to understand what needs to be done for ioctls. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
177 lines
3.8 KiB
C
177 lines
3.8 KiB
C
/*
|
|
* FUSE fioc_ll_client: FUSE ioctl example client for low-level API
|
|
* Copyright (C) 2008 SUSE Linux Products GmbH
|
|
* Copyright (C) 2008 Tejun Heo <teheo@suse.de>
|
|
* Copyright (C) 2024 libfuse maintainers
|
|
*
|
|
* This program can be distributed under the terms of the GNU GPLv2.
|
|
* See the file GPL2.txt.
|
|
*/
|
|
|
|
/** @file
|
|
*
|
|
* This program tests the ioctl_ll.c example file system.
|
|
* It tests both restricted ioctls (FIOC_GET_SIZE, FIOC_SET_SIZE) and
|
|
* unrestricted ioctls (FIOC_READ, FIOC_WRITE).
|
|
*
|
|
* Compile with:
|
|
*
|
|
* gcc -Wall ioctl_ll_client.c -o ioctl_ll_client
|
|
*
|
|
* ## Source code ##
|
|
* \include ioctl_ll_client.c
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/ioctl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include "ioctl.h"
|
|
|
|
static const char *usage =
|
|
"Usage: ioctl_ll_client <command> <fioc_file> [args]\n"
|
|
"\n"
|
|
"Commands:\n"
|
|
" get_size Get the current size (restricted ioctl)\n"
|
|
" set_size <size> Set the size (restricted ioctl)\n"
|
|
" read <offset> <size> Read data via ioctl (unrestricted)\n"
|
|
" write <offset> <data> Write data via ioctl (unrestricted)\n"
|
|
"\n"
|
|
"Examples:\n"
|
|
" ioctl_ll_client get_size /mnt/fioc\n"
|
|
" ioctl_ll_client set_size /mnt/fioc 100\n"
|
|
" ioctl_ll_client read /mnt/fioc 0 10\n"
|
|
" ioctl_ll_client write /mnt/fioc 0 hello\n"
|
|
"\n";
|
|
|
|
static int do_get_size(int fd)
|
|
{
|
|
size_t size;
|
|
|
|
if (ioctl(fd, FIOC_GET_SIZE, &size)) {
|
|
perror("ioctl(FIOC_GET_SIZE)");
|
|
return 1;
|
|
}
|
|
printf("%zu\n", size);
|
|
return 0;
|
|
}
|
|
|
|
static int do_set_size(int fd, const char *size_str)
|
|
{
|
|
size_t size = strtoul(size_str, NULL, 0);
|
|
|
|
if (ioctl(fd, FIOC_SET_SIZE, &size)) {
|
|
perror("ioctl(FIOC_SET_SIZE)");
|
|
return 1;
|
|
}
|
|
printf("Size set to %zu\n", size);
|
|
return 0;
|
|
}
|
|
|
|
static int do_read(int fd, const char *offset_str, const char *size_str)
|
|
{
|
|
struct fioc_rw_arg arg;
|
|
char *buf;
|
|
ssize_t ret;
|
|
size_t sz = strtoul(size_str, NULL, 0);
|
|
|
|
buf = malloc(sz + 1);
|
|
if (!buf) {
|
|
perror("malloc");
|
|
return 1;
|
|
}
|
|
|
|
memset(&arg, 0, sizeof(arg));
|
|
arg.offset = strtol(offset_str, NULL, 0);
|
|
arg.buf = buf;
|
|
arg.size = sz;
|
|
|
|
ret = ioctl(fd, FIOC_READ, &arg);
|
|
if (ret < 0) {
|
|
perror("ioctl(FIOC_READ)");
|
|
free(buf);
|
|
return 1;
|
|
}
|
|
|
|
buf[ret] = '\0';
|
|
printf("Read %zd bytes (prev_size=%zu, new_size=%zu): %s\n",
|
|
ret, arg.prev_size, arg.new_size, buf);
|
|
free(buf);
|
|
return 0;
|
|
}
|
|
|
|
static int do_write(int fd, const char *offset_str, const char *data)
|
|
{
|
|
struct fioc_rw_arg arg;
|
|
ssize_t ret;
|
|
|
|
memset(&arg, 0, sizeof(arg));
|
|
arg.offset = strtol(offset_str, NULL, 0);
|
|
arg.buf = (void *)data;
|
|
arg.size = strlen(data);
|
|
|
|
ret = ioctl(fd, FIOC_WRITE, &arg);
|
|
if (ret < 0) {
|
|
perror("ioctl(FIOC_WRITE)");
|
|
return 1;
|
|
}
|
|
|
|
printf("Wrote %zd bytes (prev_size=%zu, new_size=%zu)\n",
|
|
ret, arg.prev_size, arg.new_size);
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int fd;
|
|
int ret = 0;
|
|
|
|
if (argc < 3) {
|
|
fprintf(stderr, "%s", usage);
|
|
return 1;
|
|
}
|
|
|
|
fd = open(argv[2], O_RDWR);
|
|
if (fd < 0) {
|
|
perror("open");
|
|
return 1;
|
|
}
|
|
|
|
if (strcmp(argv[1], "get_size") == 0) {
|
|
ret = do_get_size(fd);
|
|
} else if (strcmp(argv[1], "set_size") == 0) {
|
|
if (argc < 4) {
|
|
fprintf(stderr, "set_size requires a size argument\n");
|
|
ret = 1;
|
|
} else {
|
|
ret = do_set_size(fd, argv[3]);
|
|
}
|
|
} else if (strcmp(argv[1], "read") == 0) {
|
|
if (argc < 5) {
|
|
fprintf(stderr, "read requires offset and size\n");
|
|
ret = 1;
|
|
} else {
|
|
ret = do_read(fd, argv[3], argv[4]);
|
|
}
|
|
} else if (strcmp(argv[1], "write") == 0) {
|
|
if (argc < 5) {
|
|
fprintf(stderr, "write requires offset and data\n");
|
|
ret = 1;
|
|
} else {
|
|
ret = do_write(fd, argv[3], argv[4]);
|
|
}
|
|
} else {
|
|
fprintf(stderr, "Unknown command: %s\n", argv[1]);
|
|
fprintf(stderr, "%s", usage);
|
|
ret = 1;
|
|
}
|
|
|
|
close(fd);
|
|
return ret;
|
|
}
|
|
|