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 COPYING. 8*/ 9 10/** @file 11 * 12 * This program tests the cuse.c example file system. 13 * 14 * Example usage (assuming that /dev/foobar is a CUSE device provided 15 * by the cuse.c example file system): 16 * 17 * $ cuse_client /dev/foobar s 18 * 0 19 * 20 * $ echo "hello" | cuse_client /dev/foobar w 6 21 * Writing 6 bytes 22 * transferred 6 bytes (0 -> 6) 23 * 24 * $ cuse_client /dev/foobar s 25 * 6 26 * 27 * $ cuse_client /dev/foobar r 10 28 * hello 29 * transferred 6 bytes (6 -> 6) 30 * 31 * Compiling this example 32 * 33 * gcc -Wall cuse_client.c -o cuse_client 34 * 35 * ## Source Code ## 36 * \include cuse_client.c 37 */ 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 51const char *usage = 52"Usage: cuse_client FIOC_FILE COMMAND\n" 53"\n" 54"COMMANDS\n" 55" s [SIZE] : get size if SIZE is omitted, set size otherwise\n" 56" r SIZE [OFF] : read SIZE bytes @ OFF (dfl 0) and output to stdout\n" 57" w SIZE [OFF] : write SIZE bytes @ OFF (dfl 0) from stdin\n" 58"\n"; 59 60static int do_rw(int fd, int is_read, size_t size, off_t offset, 61 size_t *prev_size, size_t *new_size) 62{ 63 struct fioc_rw_arg arg = { .offset = offset }; 64 ssize_t ret; 65 66 arg.buf = calloc(1, size); 67 if (!arg.buf) { 68 fprintf(stderr, "failed to allocated %zu bytes\n", size); 69 return -1; 70 } 71 72 if (is_read) { 73 arg.size = size; 74 ret = ioctl(fd, FIOC_READ, &arg); 75 if (ret >= 0) 76 fwrite(arg.buf, 1, ret, stdout); 77 } else { 78 arg.size = fread(arg.buf, 1, size, stdin); 79 fprintf(stderr, "Writing %zu bytes\n", arg.size); 80 ret = ioctl(fd, FIOC_WRITE, &arg); 81 } 82 83 if (ret >= 0) { 84 *prev_size = arg.prev_size; 85 *new_size = arg.new_size; 86 } else 87 perror("ioctl"); 88 89 free(arg.buf); 90 return ret; 91} 92 93int main(int argc, char **argv) 94{ 95 size_t param[2] = { }; 96 size_t size, prev_size = 0, new_size = 0; 97 char cmd; 98 int fd, i, rc; 99 100 if (argc < 3) 101 goto usage; 102 103 fd = open(argv[1], O_RDWR); 104 if (fd < 0) { 105 perror("open"); 106 return 1; 107 } 108 109 cmd = tolower(argv[2][0]); 110 argc -= 3; 111 argv += 3; 112 113 for (i = 0; i < argc; i++) { 114 char *endp; 115 param[i] = strtoul(argv[i], &endp, 0); 116 if (endp == argv[i] || *endp != '\0') 117 goto usage; 118 } 119 120 switch (cmd) { 121 case 's': 122 if (!argc) { 123 if (ioctl(fd, FIOC_GET_SIZE, &size)) { 124 perror("ioctl"); 125 goto error; 126 } 127 printf("%zu\n", size); 128 } else { 129 size = param[0]; 130 if (ioctl(fd, FIOC_SET_SIZE, &size)) { 131 perror("ioctl"); 132 goto error; 133 } 134 } 135 close(fd); 136 return 0; 137 138 case 'r': 139 case 'w': 140 rc = do_rw(fd, cmd == 'r', param[0], param[1], 141 &prev_size, &new_size); 142 if (rc < 0) 143 goto error; 144 fprintf(stderr, "transferred %d bytes (%zu -> %zu)\n", 145 rc, prev_size, new_size); 146 close(fd); 147 return 0; 148 } 149 150usage: 151 fprintf(stderr, "%s", usage); 152 return 1; 153 154error: 155 close(fd); 156 return 1; 157} 158