12 Commits

Author SHA1 Message Date
Godzil
fa61f857a7 Reformating to try to match better kernel coding style. 2018-05-10 15:38:45 +01:00
Godzil
684a150a21 Remove support for user provided class as it is way too problematic to recover existing classes. 2018-05-10 15:28:13 +01:00
Godzil
4db826209e Add (and use) git describe to get module version. 2018-05-10 15:20:52 +01:00
Godzil
1b50ad2d74 Update some copyrights 2018-05-10 15:20:06 +01:00
Godzil
48264ec40a Add preliminary support for more recent kernel (~4.15)
It is currently building with a Debian 4.15.11-1, but hasn't been tested
and is expecting to crash really hard. Do no try unless you are ready to
hard crash your system. It should support most version between the
~2.6.32 and this 4.15.11.
2018-05-08 15:39:51 +01:00
Godzil
1afa952fb0 Fix PEBCAK 2012-12-04 14:26:06 +01:00
Godzil
b208b10645 I was a bit optimistic. 2.6.32 does not support DECLARE_SEMAPHORE.
Now use DECLARE_MUTEX up to 2.6.35 (need to be checked)

Signed-off-by: Godzil <godzil@godzil.net>
2012-10-16 20:07:34 +02:00
Godzil
3c0b0cdd4b Correct support for kernel <2.6.33 2012-09-10 20:12:13 +02:00
Godzil
9f496af46b Correct fusd_destroy to lock and check before freeing. 2012-07-10 14:06:27 +02:00
Godzil
fd1f2a7374 Cosmetics, cosmetics and cosmetics. 2012-07-10 14:06:00 +02:00
Godzil
0678a66b3c add locking mechanism in the fusd_file_info_t structure to prevent potential race conditions. 2012-07-10 14:00:05 +02:00
Godzil
542d87ea75 Update libfusd accordingly with latest changes in kfusd. 2012-07-10 13:49:37 +02:00
6 changed files with 2146 additions and 2300 deletions

View File

@@ -6,12 +6,16 @@ FUSD: A Linux Framework for User-Space Devices
This is FUSD snapshot 20110401, released 18 January 2012. This fork is based
on the found on the xiph.org SVN tracker. ( http://svn.xiph.org/trunk/fusd )
They seems to no longuer update this tool (since 11 January 2007) and since it
longuer compile with recent Linux kernel (at around 2.6.21) and since I need
it in personal project, I ported it to newer version (current version is 2.6.32)
They seems to no longer update this tool (since 11 January 2007) and since it
longer compile with recent Linux kernel (at around 2.6.21) and since I need
it in personal project, I ported it to newer version (current version is 2.6.32).
It is currently no officialy supporting newer kernel, but changes are currently
going on to support newer kernel up to 4.15. It is currently building under this
line, but don't expect it to work.
Some feature are still missing missing or buggy form the Xiph version (due to
changes on the kernel source tree), but it's completly useable.
changes on the kernel source tree), but it is still usable.
The official URL for this fork is:
@@ -53,7 +57,7 @@ include the following rule:
5. Verify the fusd devices /dev/fusd/status and /dev/fusd/control
exist. If the modprobe succeeds but no fusd devices appear,
doublecheck the udev rule config change and make sure udevd restarted
double-check the udev rule config change and make sure udevd restarted
successfully. The kfusd kernel module must be inserted after udev has
been correctly configured and restarted.

View File

@@ -66,6 +66,8 @@ __BEGIN_DECLS
#define FUSD_KOR_HACKED_VERSION
#ifndef __KERNEL__
struct fusd_file_info; /* forward decl */
typedef
@@ -105,6 +107,7 @@ struct fusd_file_info {
/* other info might be added later, e.g. state needed to complete
operations... */
pthread_mutex_t lock;
/* request message associated with this call */
int fd;
@@ -112,8 +115,8 @@ struct fusd_file_info {
} fusd_file_info_t;
#define FILE_LOCK(__f) pthread_mutex_lock(&__f->lock)
#define FILE_UNLOCK(__f) pthread_mutex_unlock(&__f->lock)
/*************************** Library Functions ****************************/
@@ -278,6 +281,8 @@ static inline int fusd_get_poll_diff_cached_state(struct fusd_file_info *file)
/* returns static string representing the flagset (e.g. RWE) */
char *fusd_unparse_flags(int flags);
#endif /* !__KERNEL__ */
#ifndef __KERNEL__
__END_DECLS
#endif

View File

@@ -273,7 +273,7 @@ static void fusd_vfree(void *ptr);
/* Functions like this should be in the kernel, but they are not. Sigh. */
# ifdef CONFIG_SMP
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
DECLARE_MUTEX(atomic_ops);
#else
DEFINE_SEMAPHORE(atomic_ops);

View File

@@ -5,11 +5,11 @@ else
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
ROOTFS ?=
GIT_DESCRIBE = $(shell git describe --dirty --tags)
KERNEL_VER ?= 2.6.32.7
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) EXTRA_CFLAGS=-I$(PWD)/../include modules
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) EXTRA_CFLAGS="-I$(PWD)/../include -DGIT_DESCRIBE='\"${GIT_DESCRIBE}\"'" V=1 modules
install:
install -d -m 0755 $(ROOTFS)/lib/modules/$(KERNEL_VER)/kernel/drivers/misc

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* fusd userspace library: functions that know how to properly talk
@@ -53,6 +53,11 @@ char libfusd_c_id[] = "$Id: libfusd.c 12351 2007-01-19 07:22:54Z xiphmont $";
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "fusd.h"
#include "fusd_msg.h"
@@ -72,7 +77,7 @@ char *dev_root = NULL;
* struct for each fusd fd.
*/
static fusd_file_operations_t fusd_fops_set[FD_SETSIZE];
fusd_file_operations_t null_fops = { NULL };
fusd_file_operations_t null_fops = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
/*
* accessor macros
@@ -99,7 +104,8 @@ void fusd_init()
{
static int fusd_init_needed = 1;
if (fusd_init_needed) {
if (fusd_init_needed)
{
int i;
fusd_init_needed = 0;
@@ -123,7 +129,8 @@ int fusd_register(const char *name, const char* clazz, const char* devname, mode
fusd_init();
/* make sure the name is valid and we have a valid set of fops... */
if (name == NULL || fops == NULL) {
if (name == NULL || fops == NULL)
{
fprintf(stderr, "fusd_register: invalid name or fops argument\n");
retval = -EINVAL;
goto done;
@@ -134,27 +141,33 @@ int fusd_register(const char *name, const char* clazz, const char* devname, mode
* to register are SKIP_PREFIX (usually "/dev/"), skip over them.
*/
if (dev_root != NULL && strlen(name) > strlen(dev_root) &&
!strncmp(name, dev_root, strlen(dev_root))) {
!strncmp(name, dev_root, strlen(dev_root)))
{
name += strlen(dev_root);
}
if (strlen(name) > FUSD_MAX_NAME_LENGTH) {
fprintf(stderr, "name '%s' too long, sorry :(", name);
if (strlen(name) > FUSD_MAX_NAME_LENGTH)
{
fprintf(stderr, "libfusd: name '%s' too long, sorry :(\n", name);
retval = -EINVAL;
goto done;
}
/* open the fusd control channel */
if ((fd = open(FUSD_CONTROL_DEVNAME, O_RDWR | O_NONBLOCK)) < 0) {
if ((fd = open(FUSD_CONTROL_DEVNAME, O_RDWR | O_NONBLOCK)) < 0)
{
/* if the problem is that /dev/fusd does not exist, return the
* message "Package not installed", which is hopefully more
* illuminating than "no such file or directory" */
if (errno == ENOENT) {
if (errno == ENOENT)
{
fprintf(stderr, "libfusd: %s does not exist; ensure FUSD's kernel module is installed\n",
FUSD_CONTROL_DEVNAME);
retval = -ENOPKG;
} else {
}
else
{
perror("libfusd: trying to open FUSD control channel");
retval = -errno;
}
@@ -162,7 +175,8 @@ int fusd_register(const char *name, const char* clazz, const char* devname, mode
}
/* fd in use? */
if (FUSD_FD_VALID(fd)) {
if (FUSD_FD_VALID(fd))
{
retval = -EBADF;
goto done;
}
@@ -179,7 +193,8 @@ int fusd_register(const char *name, const char* clazz, const char* devname, mode
message.parm.register_msg.device_info = device_info;
/* make the request */
if (write(fd, &message, sizeof(fusd_msg_t)) < 0) {
if (write(fd, &message, sizeof(fusd_msg_t)) < 0)
{
retval = -errno;
goto done;
}
@@ -190,34 +205,38 @@ int fusd_register(const char *name, const char* clazz, const char* devname, mode
/* success! */
done:
if (retval < 0) {
if (retval < 0)
{
if (fd >= 0)
close(fd);
errno = -retval;
retval = -1;
} else {
}
else
{
errno = 0;
retval = fd;
}
return retval;
}
int fusd_unregister(int fd)
{
if (FUSD_FD_VALID(fd)) {
int ret = -1;
if (FUSD_FD_VALID(fd))
{
/* clear fd location */
FUSD_SET_FOPS(fd, &null_fops);
FD_CLR(fd, &fusd_fds);
/* close */
return close(fd);
ret = close(fd);
}
else {
else
{
errno = EBADF;
return -1;
}
return ret;
}
@@ -236,21 +255,25 @@ void fusd_run(void)
int i;
/* locate maxmimum fd in use */
for (maxfd=0, i=0; i < FD_SETSIZE; i++) {
if (FD_ISSET(i, &fusd_fds)) {
for (maxfd=0, i=0; i < FD_SETSIZE; i++)
{
if (FD_ISSET(i, &fusd_fds))
{
maxfd = i;
}
}
maxfd++;
while (1) {
while (1)
{
/* select */
memmove(&tfds, &fusd_fds, sizeof(fd_set));
status = select(maxfd, &tfds, NULL, NULL, NULL);
/* error? */
if (status < 0) {
if (status < 0)
{
perror("libfusd: fusd_run: error on select");
continue;
}
@@ -258,14 +281,13 @@ void fusd_run(void)
/* readable? */
for (i = 0; i < maxfd; i++)
if (FD_ISSET(i, &tfds))
fusd_dispatch(i);
fusd_dispatch(i);
}
}
/************************************************************************/
/* reads a fusd kernel-to-userspace message from fd, and puts a
* fusd_msg into the memory pointed to by msg (we assume we are passed
* a buffer managed by the caller). if there is a data portion to the
@@ -274,39 +296,51 @@ void fusd_run(void)
* managed by the caller. */
static int fusd_get_message(int fd, fusd_msg_t *msg)
{
int ret;
/* read the header part into the kernel */
if (read(fd, msg, sizeof(fusd_msg_t)) < 0) {
if (read(fd, msg, sizeof(fusd_msg_t)) < 0)
{
if (errno != EAGAIN)
perror("error talking to FUSD control channel on header read");
return -errno;
ret = -errno;
goto exit;
}
msg->data = NULL; /* pointers in kernelspace have no meaning */
if (msg->magic != FUSD_MSG_MAGIC) {
fprintf(stderr, "libfusd magic number failure\n");
return -EINVAL;
if (msg->magic != FUSD_MSG_MAGIC)
{
fprintf(stderr, "libfusd: magic number failure\n");
ret = -EINVAL;
goto exit;
}
/* if there's a data part to the message, read it from the kernel. */
if (msg->datalen) {
if ((msg->data = malloc(msg->datalen + 1)) == NULL) {
if (msg->datalen)
{
if ((msg->data = malloc(msg->datalen + 1)) == NULL)
{
fprintf(stderr, "libfusd: can't allocate memory\n");
return -ENOMEM; /* this is bad, we are now unsynced */
ret = -ENOMEM; /* this is bad, we are now unsynced */
goto exit;
}
if (read(fd, msg->data, msg->datalen) < 0) {
if (read(fd, msg->data, msg->datalen) < 0)
{
perror("error talking to FUSD control channel on data read");
free(msg->data);
msg->data = NULL;
return -EIO;
ret = -EIO;
goto exit;
}
/* For convenience, we now ensure that the byte *after* the buffer
* is set to 0. (Note we malloc'd one extra byte above.) */
msg->data[msg->datalen] = '\0';
}
return 0;
ret = 0;
exit:
return ret;
}
@@ -318,11 +352,14 @@ void fusd_fdset_add(fd_set *set, int *max)
{
int i;
for (i = 0; i < FD_SETSIZE; i++) {
if (FD_ISSET(i, &fusd_fds)) {
for (i = 0; i < FD_SETSIZE; i++)
{
if (FD_ISSET(i, &fusd_fds))
{
FD_SET(i, set);
if (i > *max) {
*max = i;
if (i > *max)
{
*max = i;
}
}
}
@@ -340,6 +377,7 @@ void fusd_dispatch_fdset(fd_set *set)
for (i = 0; i < FD_SETSIZE; i++)
if (FD_ISSET(i, set) && FD_ISSET(i, &fusd_fds))
fusd_dispatch(i);
}
@@ -361,14 +399,16 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
int user_retval = 0; /* returned to the user who made the syscall */
/* check for valid, look up ops */
if (fops == NULL) {
if (fops == NULL)
{
fprintf(stderr, "fusd_dispatch: no fops provided!\n");
driver_retval = -EBADF;
goto out_noreply;
}
/* allocate memory for fusd_msg_t */
if ((msg = malloc(sizeof(fusd_msg_t))) == NULL) {
if ((msg = malloc(sizeof(fusd_msg_t))) == NULL)
{
driver_retval = -ENOMEM;
fprintf(stderr, "libfusd: can't allocate memory\n");
goto out_noreply;
@@ -381,7 +421,8 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
/* allocate file info struct */
file = malloc(sizeof(fusd_file_info_t));
if (NULL == file) {
if (NULL == file)
{
fprintf(stderr, "libfusd: can't allocate memory\n");
driver_retval = -ENOMEM;
goto out_noreply;
@@ -389,6 +430,11 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
/* fill the file info struct */
memset(file, '\0', sizeof(fusd_file_info_t));
pthread_mutex_init(&file->lock, NULL);
FILE_LOCK(file);
file->fd = fd;
file->device_info = msg->parm.fops_msg.device_info;
file->private_data = msg->parm.fops_msg.private_info;
@@ -398,49 +444,62 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
file->gid = msg->parm.fops_msg.gid;
file->fusd_msg = msg;
FILE_UNLOCK(file);
/* right now we only handle fops requests */
if (msg->cmd != FUSD_FOPS_CALL && msg->cmd != FUSD_FOPS_NONBLOCK &&
msg->cmd != FUSD_FOPS_CALL_DROPREPLY) {
msg->cmd != FUSD_FOPS_CALL_DROPREPLY)
{
fprintf(stderr, "libfusd: got unknown msg->cmd from kernel\n");
user_retval = -EINVAL;
goto send_reply;
}
/* dispatch on operation type */
user_retval = -ENOSYS;
//printf("dispatch_one: subcmd: %d - ", msg->subcmd);
switch (msg->subcmd) {
switch (msg->subcmd)
{
case FUSD_OPEN:
//printf("FUSD_OPEN\n");
if (fops && fops->open)
user_retval = fops->open(file);
break;
case FUSD_CLOSE:
//printf("FUSD_CLOSE\n");
if (fops && fops->close)
user_retval = fops->close(file);
break;
case FUSD_READ:
//printf("FUSD_READ\n");
/* allocate a buffer and make the call */
if (fops && fops->read) {
if ((msg->data = malloc(msg->parm.fops_msg.length)) == NULL) {
user_retval = -ENOMEM;
fprintf(stderr, "libfusd: can't allocate memory\n");
} else {
msg->datalen = msg->parm.fops_msg.length;
user_retval = fops->read(file, msg->data, msg->datalen,
&msg->parm.fops_msg.offset);
if (fops && fops->read)
{
if ((msg->data = malloc(msg->parm.fops_msg.length)) == NULL)
{
user_retval = -ENOMEM;
fprintf(stderr, "libfusd: can't allocate memory\n");
}
else
{
msg->datalen = msg->parm.fops_msg.length;
user_retval = fops->read(file, msg->data, msg->datalen,
&msg->parm.fops_msg.offset);
}
}
break;
case FUSD_WRITE:
//printf("FUSD_WRITE\n");
if (fops && fops->write)
user_retval = fops->write(file, msg->data, msg->datalen,
&msg->parm.fops_msg.offset);
break;
case FUSD_MMAP:
//printf("FUSD_MMAP\n");
if (fops && fops->mmap)
@@ -449,54 +508,58 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
&msg->parm.fops_msg.arg.ptr_arg, &msg->parm.fops_msg.length);
}
break;
case FUSD_IOCTL:
//printf("FUSD_IOCTL\n");
if (fops && fops->ioctl) {
if (fops && fops->ioctl)
{
/* in the case of an ioctl read, allocate a buffer for the
* driver to write to, IF there isn't already a buffer. (there
* might already be a buffer if this is a read+write) */
if ((_IOC_DIR(msg->parm.fops_msg.cmd) & _IOC_READ) &&
msg->data == NULL) {
msg->datalen = _IOC_SIZE(msg->parm.fops_msg.cmd);
if ((msg->data = malloc(msg->datalen)) == NULL) {
user_retval = -ENOMEM;
break;
}
msg->data == NULL)
{
msg->datalen = _IOC_SIZE(msg->parm.fops_msg.cmd);
if ((msg->data = malloc(msg->datalen)) == NULL)
{
user_retval = -ENOMEM;
break;
}
}
if (msg->data != NULL)
user_retval = fops->ioctl(file, msg->parm.fops_msg.cmd, msg->data);
user_retval = fops->ioctl(file, msg->parm.fops_msg.cmd, msg->data);
else
user_retval = fops->ioctl(file, msg->parm.fops_msg.cmd,
(void *) msg->parm.fops_msg.arg.ptr_arg);
user_retval = fops->ioctl(file, msg->parm.fops_msg.cmd,
(void *) msg->parm.fops_msg.arg.ptr_arg);
}
break;
case FUSD_POLL_DIFF:
//printf("FUSD_POLL_DIFF\n");
/* This callback requests notification when an event occurs on a file,
* e.g. becoming readable or writable */
if (fops && fops->poll_diff)
user_retval = fops->poll_diff(file, msg->parm.fops_msg.cmd);
break;
break;
case FUSD_UNBLOCK:
//printf("FUSD_UNBLOCK\n");
/* This callback is called when a system call is interrupted */
if (fops && fops->unblock)
user_retval = fops->unblock(file);
user_retval = fops->unblock(file);
break;
default:
fprintf(stderr, "libfusd: Got unsupported operation\n");
user_retval = -ENOSYS;
break;
}
goto send_reply;
/* out_noreply is only used for handling errors */
out_noreply:
out_noreply:
if (msg->data != NULL)
free(msg->data);
if (msg != NULL)
@@ -504,21 +567,26 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
goto done;
/* send_reply is only used for success */
send_reply:
if (-user_retval <= 0xff) {
send_reply:
if (-user_retval <= 0xff)
{
/* 0xff is the maximum legal return value (?) - return val to user */
driver_retval = fusd_return(file, user_retval);
} else {
}
else
{
/* if we got a FUSD_NOREPLY, don't free the msg structure */
driver_retval = 0;
}
/* this is common to both errors and success */
done:
if (driver_retval < 0) {
done:
if (driver_retval < 0)
{
errno = -driver_retval;
driver_retval = -1;
}
return driver_retval;
}
@@ -538,7 +606,8 @@ void fusd_dispatch(int fd)
fusd_file_operations_t *fops = NULL;
/* make sure we have a valid FD, and get its fops structure */
if (!FUSD_FD_VALID(fd)) {
if (!FUSD_FD_VALID(fd))
{
errno = EBADF;
retval = -1;
fprintf(stderr, "libfusd: not a valid FUSD FD\n");
@@ -547,7 +616,8 @@ void fusd_dispatch(int fd)
fops = FUSD_GET_FOPS(fd);
/* now keep dispatching until a dispatch returns an error */
do {
do
{
retval = fusd_dispatch_one(fd, fops);
if (retval >= 0)
@@ -557,14 +627,16 @@ void fusd_dispatch(int fd)
/* if we've dispatched at least one message successfully, and then
* stopped because of EAGAIN - do not report an error. this is the
* common case. */
if (num_dispatches > 0 && errno == EAGAIN) {
if (num_dispatches > 0 && errno == EAGAIN)
{
retval = 0;
errno = 0;
}
out:
if (retval < 0 && errno != EPIPE)
fprintf(stderr, "libfusd: fusd_dispatch error on fd %d: [%d] %m \n", fd, retval);
fprintf(stderr, "libfusd: fusd_dispatch error on fd %d: [%d] %m\n", fd, retval);
}
@@ -578,13 +650,26 @@ void fusd_dispatch(int fd)
*/
void fusd_destroy(struct fusd_file_info *file)
{
if (file == NULL)
return;
if (file == NULL)
return;
if (file->fusd_msg->data != NULL)
free(file->fusd_msg->data);
free(file->fusd_msg);
free(file);
FILE_LOCK(file);
if (file->fusd_msg != NULL)
{
if (file->fusd_msg->data != NULL)
{
free(file->fusd_msg->data);
file->fusd_msg->data = NULL;
}
free(file->fusd_msg);
file->fusd_msg = NULL;
}
FILE_UNLOCK(file);
pthread_mutex_destroy(&file->lock);
free(file);
}
@@ -600,22 +685,31 @@ int fusd_return(fusd_file_info_t *file, ssize_t retval)
fusd_msg_t *msg = NULL;
int fd;
int driver_retval = 0;
int ret;
struct iovec iov[2];
if (file == NULL) {
if (file == NULL)
{
fprintf(stderr, "fusd_return: NULL file\n");
return -EINVAL;
ret = -EINVAL;
goto exit;
}
FILE_LOCK(file);
fd = file->fd;
if (!FUSD_FD_VALID(fd)) {
if (!FUSD_FD_VALID(fd))
{
fprintf(stderr, "fusd_return: badfd (fd %d)\n", fd);
return -EBADF;
ret = -EBADF;
goto exit_unlock;
}
if ((msg = file->fusd_msg) == NULL) {
if ((msg = file->fusd_msg) == NULL)
{
fprintf(stderr, "fusd_return: fusd_msg is gone\n");
return -EINVAL;
ret = -EINVAL;
goto exit_unlock;
}
/* if this was a "DONTREPLY" message, just free the struct */
@@ -623,24 +717,29 @@ int fusd_return(fusd_file_info_t *file, ssize_t retval)
goto free_memory;
/* do we copy data back to kernel? how much? */
switch(msg->subcmd) {
switch(msg->subcmd)
{
case FUSD_READ:
/* these operations can return data to userspace */
if (retval > 0) {
msg->datalen = MIN(retval, msg->parm.fops_msg.length);
if (retval > 0)
{
msg->datalen = MIN((int)retval, (int)msg->parm.fops_msg.length);
retval = msg->datalen;
} else {
}
else
{
msg->datalen = 0;
}
break;
case FUSD_IOCTL:
/* ioctl CAN (in read mode) return data to userspace */
if ((retval == 0) &&
(_IOC_DIR(msg->parm.fops_msg.cmd) & _IOC_READ))
if (/*(retval == 0) && */ (_IOC_DIR(msg->parm.fops_msg.cmd) & _IOC_READ) )
msg->datalen = _IOC_SIZE(msg->parm.fops_msg.cmd);
else
msg->datalen = 0;
break;
default:
/* open, close, write, etc. do not return data */
msg->datalen = 0;
@@ -656,29 +755,35 @@ int fusd_return(fusd_file_info_t *file, ssize_t retval)
/* pid is NOT copied back. */
/* send message to kernel */
if (msg->datalen && msg->data != NULL) {
if (msg->datalen && msg->data != NULL)
{
//printf("(msg->datalen [%d] && msg->data != NULL [%p]", msg->datalen, msg->data);
iov[0].iov_base = msg;
iov[0].iov_len = sizeof(fusd_msg_t);
iov[1].iov_base = msg->data;
iov[1].iov_len = msg->datalen;
#if 0
driver_retval = writev(fd, iov, 2);
#else
driver_retval = ioctl(fd, 0xb16b00b5, iov);
#endif
}
else {
else
{
driver_retval = write(fd, msg, sizeof(fusd_msg_t));
}
free_memory:
free_memory:
FILE_UNLOCK(file);
fusd_destroy(file);
ret = 0;
if (driver_retval < 0)
return -errno;
else
return 0;
ret = -errno;
goto exit;
exit_unlock:
FILE_UNLOCK(file);
exit:
return ret;
}
@@ -690,12 +795,12 @@ char *fusd_unparse_flags(int flags)
static char ringbuf[RING][5];
char *s = ringbuf[i];
i = (i + 1) % RING;
sprintf(s, "%c%c%c",
sprintf(s, "%c%c%c",
(flags & FUSD_NOTIFY_INPUT)?'R':'-',
(flags & FUSD_NOTIFY_OUTPUT)?'W':'-',
(flags & FUSD_NOTIFY_EXCEPT)?'E':'-');
return s;
}
#undef RING