libfuse
cuse_client.c
Go to the documentation of this file.
1/*
2 FUSE fioclient: FUSE ioctl example client
3 Copyright (C) 2008 SUSE Linux Products GmbH
4 Copyright (C) 2008 Tejun Heo <teheo@suse.de>
5
6 This program can be distributed under the terms of the GNU GPLv2.
7 See the file GPL2.txt.
8*/
9
38
39
40#include <sys/types.h>
41#include <fcntl.h>
42#include <sys/stat.h>
43#include <sys/ioctl.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <ctype.h>
47#include <errno.h>
48#include <unistd.h>
49#include "ioctl.h"
50
51/* keeps a mistyped SIZE from asking for the machine's memory */
52#define MAX_XFER_SIZE (16 * 1024 * 1024)
53
54const char *usage =
55"Usage: cuse_client FIOC_FILE COMMAND\n"
56"\n"
57"COMMANDS\n"
58" s [SIZE] : get size if SIZE is omitted, set size otherwise\n"
59" r SIZE [OFF] : read SIZE bytes @ OFF (dfl 0) and output to stdout\n"
60" w SIZE [OFF] : write SIZE bytes @ OFF (dfl 0) from stdin\n"
61"\n";
62
63static int do_rw(int fd, int is_read, size_t size, off_t offset,
64 size_t *prev_size, size_t *new_size)
65{
66 struct fioc_rw_arg arg = { .offset = offset };
67 ssize_t ret;
68
69 if (size > MAX_XFER_SIZE) {
70 fprintf(stderr, "size %zu exceeds limit of %d bytes\n",
71 size, MAX_XFER_SIZE);
72 return -1;
73 }
74
75 arg.buf = calloc(1, size);
76 if (!arg.buf) {
77 fprintf(stderr, "failed to allocated %zu bytes\n", size);
78 return -1;
79 }
80
81 if (is_read) {
82 arg.size = size;
83 ret = ioctl(fd, FIOC_READ, &arg);
84 if (ret >= 0)
85 fwrite(arg.buf, 1, ret, stdout);
86 } else {
87 arg.size = fread(arg.buf, 1, size, stdin);
88 fprintf(stderr, "Writing %zu bytes\n", arg.size);
89 ret = ioctl(fd, FIOC_WRITE, &arg);
90 }
91
92 if (ret >= 0) {
93 *prev_size = arg.prev_size;
94 *new_size = arg.new_size;
95 } else
96 perror("ioctl");
97
98 free(arg.buf);
99 return ret;
100}
101
102int main(int argc, char **argv)
103{
104 size_t param[2] = { };
105 size_t size, prev_size = 0, new_size = 0;
106 char cmd;
107 int fd, i, rc;
108
109 if (argc < 3)
110 goto usage;
111
112 fd = open(argv[1], O_RDWR);
113 if (fd < 0) {
114 perror("open");
115 return 1;
116 }
117
118 cmd = tolower(argv[2][0]);
119 argc -= 3;
120 argv += 3;
121
122 for (i = 0; i < argc; i++) {
123 char *endp;
124 param[i] = strtoul(argv[i], &endp, 0);
125 if (endp == argv[i] || *endp != '\0')
126 goto usage;
127 }
128
129 switch (cmd) {
130 case 's':
131 if (!argc) {
132 if (ioctl(fd, FIOC_GET_SIZE, &size)) {
133 perror("ioctl");
134 goto error;
135 }
136 printf("%zu\n", size);
137 } else {
138 size = param[0];
139 if (ioctl(fd, FIOC_SET_SIZE, &size)) {
140 perror("ioctl");
141 goto error;
142 }
143 }
144 close(fd);
145 return 0;
146
147 case 'r':
148 case 'w':
149 rc = do_rw(fd, cmd == 'r', param[0], param[1],
150 &prev_size, &new_size);
151 if (rc < 0)
152 goto error;
153 fprintf(stderr, "transferred %d bytes (%zu -> %zu)\n",
154 rc, prev_size, new_size);
155 close(fd);
156 return 0;
157 }
158
159usage:
160 fprintf(stderr, "%s", usage);
161 return 1;
162
163error:
164 close(fd);
165 return 1;
166}