aboutsummaryrefslogtreecommitdiff
path: root/example
diff options
context:
space:
mode:
authorGravatar Nikolaus Rath <Nikolaus@rath.org>2016-10-09 21:05:54 -0700
committerGravatar Nikolaus Rath <Nikolaus@rath.org>2016-10-09 22:03:07 -0700
commit35ce627e35d1e293b25cfa8bdec2fb82c7da4630 (patch)
tree74fbfd1e580bf741d49c243fb405b05ab8a115b1 /example
parentcf4159156ba08694feb2d75773ec49e25e8ba4fb (diff)
Renamed cuses example and added test program
An earlier version of the fioclient.c example was intended to be used together with cusexmp.c. The former has since evolved into ioctl_client.c and no longer has the function necessary to test CUSE. Therefore, we've added a new cuse_client.c that is clearly associated with the cuse.c example file system.
Diffstat (limited to 'example')
-rw-r--r--example/.gitignore3
-rw-r--r--example/Makefile.am5
-rw-r--r--example/cuse.c (renamed from example/cusexmp.c)19
-rwxr-xr-xexample/cuse_client.c153
4 files changed, 174 insertions, 6 deletions
diff --git a/example/.gitignore b/example/.gitignore
index f7cd045..6dd5004 100644
--- a/example/.gitignore
+++ b/example/.gitignore
@@ -6,7 +6,8 @@
/ioctl_client
/poll
/poll_client
-/cusexmp
+/cuse
+/cuse_client
/passthrough_ll
/notify_inval_inode
/notify_store_retrieve
diff --git a/example/Makefile.am b/example/Makefile.am
index 6d93edc..6e267a0 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -4,8 +4,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -D_REENTRANT
noinst_HEADERS = ioctl.h
noinst_PROGRAMS = passthrough passthrough_fh hello hello_ll \
ioctl ioctl_client poll poll_client \
- cusexmp passthrough_ll notify_inval_inode \
- notify_store_retrieve notify_inval_entry
+ passthrough_ll notify_inval_inode \
+ notify_store_retrieve notify_inval_entry \
+ cuse cuse_client
LDADD = ../lib/libfuse3.la
passthrough_fh_LDADD = ../lib/libfuse3.la @passthrough_fh_libs@
diff --git a/example/cusexmp.c b/example/cuse.c
index a9f3365..443d308 100644
--- a/example/cusexmp.c
+++ b/example/cuse.c
@@ -11,14 +11,24 @@
/** @file
* @tableofcontents
*
- * cusexmp.c - CUSE example: Character device in Userspace
+ * This example demonstrates how to implement a character device in
+ * userspace ("CUSE"). This is only allowed for root. The character
+ * device should appear in /dev under the specified name. It can be
+ * tested with the cuse_client.c program.
+ *
+ * Mount the file system with:
+ *
+ * cuse -f --name=mydevice
+ *
+ * You should now have a new /dev/mydevice character device. To "unmount" it,
+ * kill the "cuse" process.
*
* \section section_compile compiling this example
*
- * gcc -Wall cusexmp.c `pkg-config fuse3 --cflags --libs` -o cusexmp
+ * gcc -Wall cuse.c `pkg-config fuse3 --cflags --libs` -o cuse
*
* \section section_source the complete source
- * \include cusexmp.c
+ * \include cuse.c
*/
@@ -48,6 +58,9 @@ static const char *usage =
" --maj=MAJ|-M MAJ device major number\n"
" --min=MIN|-m MIN device minor number\n"
" --name=NAME|-n NAME device name (mandatory)\n"
+" -d -o debug enable debug output (implies -f)\n"
+" -f foreground operation\n"
+" -s disable multi-threaded operation\n"
"\n";
static int cusexmp_resize(size_t new_size)
diff --git a/example/cuse_client.c b/example/cuse_client.c
new file mode 100755
index 0000000..3e47635
--- /dev/null
+++ b/example/cuse_client.c
@@ -0,0 +1,153 @@
+/*
+ FUSE fioclient: FUSE ioctl example client
+ Copyright (C) 2008 SUSE Linux Products GmbH
+ Copyright (C) 2008 Tejun Heo <teheo@suse.de>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+/** @file
+ * @tableofcontents
+ *
+ * This program tests the cuse.c example file system.
+ *
+ * Example usage (assuming that /dev/foobar is a CUSE device provided
+ * by the cuse.c example file system):
+ *
+ * $ cuse_client /dev/foobar s
+ * 0
+ *
+ * $ echo "hello" | cuse_client /dev/foobar w 6
+ * Writing 6 bytes
+ * transferred 6 bytes (0 -> 6)
+ *
+ * $ cuse_client /dev/foobar s
+ * 6
+ *
+ * $ cuse_client /dev/foobar r 10
+ * hello
+ * transferred 6 bytes (6 -> 6)
+ *
+ * \section section_compile compiling this example
+ *
+ * gcc -Wall cuse_client.c -o cuse_client
+ *
+ * \section section_source the complete source
+ * \include cuse_client.c
+ */
+
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include "ioctl.h"
+
+const char *usage =
+"Usage: cuse_client FIOC_FILE COMMAND\n"
+"\n"
+"COMMANDS\n"
+" s [SIZE] : get size if SIZE is omitted, set size otherwise\n"
+" r SIZE [OFF] : read SIZE bytes @ OFF (dfl 0) and output to stdout\n"
+" w SIZE [OFF] : write SIZE bytes @ OFF (dfl 0) from stdin\n"
+"\n";
+
+static int do_rw(int fd, int is_read, size_t size, off_t offset,
+ size_t *prev_size, size_t *new_size)
+{
+ struct fioc_rw_arg arg = { .offset = offset };
+ ssize_t ret;
+
+ arg.buf = calloc(1, size);
+ if (!arg.buf) {
+ fprintf(stderr, "failed to allocated %zu bytes\n", size);
+ return -1;
+ }
+
+ if (is_read) {
+ arg.size = size;
+ ret = ioctl(fd, FIOC_READ, &arg);
+ if (ret >= 0)
+ fwrite(arg.buf, 1, ret, stdout);
+ } else {
+ arg.size = fread(arg.buf, 1, size, stdin);
+ fprintf(stderr, "Writing %zu bytes\n", arg.size);
+ ret = ioctl(fd, FIOC_WRITE, &arg);
+ }
+
+ if (ret >= 0) {
+ *prev_size = arg.prev_size;
+ *new_size = arg.new_size;
+ } else
+ perror("ioctl");
+
+ free(arg.buf);
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ size_t param[2] = { };
+ size_t size, prev_size = 0, new_size = 0;
+ char cmd;
+ int fd, i, rc;
+
+ if (argc < 3)
+ goto usage;
+
+ fd = open(argv[1], O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+
+ cmd = tolower(argv[2][0]);
+ argc -= 3;
+ argv += 3;
+
+ for (i = 0; i < argc; i++) {
+ char *endp;
+ param[i] = strtoul(argv[i], &endp, 0);
+ if (endp == argv[i] || *endp != '\0')
+ goto usage;
+ }
+
+ switch (cmd) {
+ case 's':
+ if (!argc) {
+ if (ioctl(fd, FIOC_GET_SIZE, &size)) {
+ perror("ioctl");
+ return 1;
+ }
+ printf("%zu\n", size);
+ } else {
+ size = param[0];
+ if (ioctl(fd, FIOC_SET_SIZE, &size)) {
+ perror("ioctl");
+ return 1;
+ }
+ }
+ return 0;
+
+ case 'r':
+ case 'w':
+ rc = do_rw(fd, cmd == 'r', param[0], param[1],
+ &prev_size, &new_size);
+ if (rc < 0)
+ return 1;
+ fprintf(stderr, "transferred %d bytes (%zu -> %zu)\n",
+ rc, prev_size, new_size);
+ return 0;
+ }
+
+ usage:
+ fprintf(stderr, "%s", usage);
+ return 1;
+}