16 Commits

Author SHA1 Message Date
Godzil
472265ae8a Add support for newers kernels, remove the temporary IOCTL and set back the writev function. 2012-07-10 12:48:23 +02:00
Godzil
789713fa0b Make change to allow to compile under kernel version > 2.6.36 (tested with a 3.2.9 kernel) 2012-04-04 11:31:16 +02:00
Godzil
efd39ff55a Update README file (and convert it to Markdown) 2012-02-13 18:36:24 +01:00
Godzil
788c45bd77 Update to lastest version 2012-01-18 14:47:25 +01:00
Godzil
a667d5412c Update some parts. 2012-01-18 14:46:38 +01:00
Godzil
8db24fbd1d small changes 2012-01-18 14:46:27 +01:00
Godzil
57dc545fad commit latest changes 2012-01-18 14:46:10 +01:00
xiphmont
bd9d3e1df3 Update the fusd examples now that multiple registration is no longer bitrotted.
git-svn-id: http://svn.xiph.org/trunk/fusd@12355 0101bb08-14d6-0310-b084-bc0e0c8e3800
2007-01-19 17:44:17 +00:00
xiphmont
cc3e84dfbf Try using the class if we're going to bother looking it up
git-svn-id: http://svn.xiph.org/trunk/fusd@12354 0101bb08-14d6-0310-b084-bc0e0c8e3800
2007-01-19 17:26:14 +00:00
xiphmont
0bf42c8088 Add code to crawl sysfs to find preexisting classes; now we can
register multiple devices of the same type for classes other than just
'sound'



git-svn-id: http://svn.xiph.org/trunk/fusd@12352 0101bb08-14d6-0310-b084-bc0e0c8e3800
2007-01-19 17:13:16 +00:00
xiphmont
41185bd56b Throttle logging so that it's not so bloody easy to accidentally take out a machine with a zombified daemon.
git-svn-id: http://svn.xiph.org/trunk/fusd@12351 0101bb08-14d6-0310-b084-bc0e0c8e3800
2007-01-19 07:22:54 +00:00
xiphmont
55b0389911 Correct a bug in which all valid interrupted write operations were being erroneously tossed (== instead of !=)
git-svn-id: http://svn.xiph.org/trunk/fusd@12350 0101bb08-14d6-0310-b084-bc0e0c8e3800
2007-01-19 04:00:37 +00:00
xiphmont
243da80fc6 Sufficiently updated docs, build system and a few of the examples for
an initial release.

Primary remaining problem: udev-style kernels don't allow registration of a
preexisting class right now.  This will need to be fixed semi-immediately.



git-svn-id: http://svn.xiph.org/trunk/fusd@12316 0101bb08-14d6-0310-b084-bc0e0c8e3800
2007-01-13 09:30:10 +00:00
xiphmont
48511c545d Build system fix-- now to update all the poor bitrotted examples so
they actually build.



git-svn-id: http://svn.xiph.org/trunk/fusd@12315 0101bb08-14d6-0310-b084-bc0e0c8e3800
2007-01-13 09:00:28 +00:00
xiphmont
0922adc0b1 Add examples to default make
git-svn-id: http://svn.xiph.org/trunk/fusd@12314 0101bb08-14d6-0310-b084-bc0e0c8e3800
2007-01-13 08:55:34 +00:00
xiphmont
5880dc8fe1 First attempt at simple examples makefile
git-svn-id: http://svn.xiph.org/trunk/fusd@12313 0101bb08-14d6-0310-b084-bc0e0c8e3800
2007-01-13 08:54:07 +00:00
23 changed files with 2729 additions and 2401 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
* ident=true

23
.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
# Ignore all generated files
*.o
*.ko
*.cmd
*.a
*.d
*.mod
*.mod.c
*.order
*.so*
*~
# Generated demo executables
examples/console-read
examples/drums
examples/drums2
examples/drums3
examples/echo
examples/helloworld
examples/ioctl
examples/logring
examples/pager
examples/uid-filter

View File

@@ -6,10 +6,10 @@ PREFIX = /usr/local
LIBDIR = $(PREFIX)/lib
INCDIR = $(PREFIX)/include
CC = gcc
LD = gcc
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)gcc
INSTALL = install
STRIP = strip
STRIP = $(CROSS_COMPILE)strip
PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
ETCDIR = /etc/$(TARGET)
@@ -23,16 +23,19 @@ export
####################################################
SUBDIRS = kfusd libfusd
SUBDIRS = kfusd libfusd examples
default:
$(MAKE) -C libfusd
$(MAKE) -C kfusd
$(MAKE) -C examples
install:
$(MAKE) -C libfusd install
$(MAKE) -C kfusd install
$(MAKE) -C examples install
clean:
$(MAKE) -C kfusd clean
$(MAKE) -C libfusd clean
$(MAKE) -C examples clean

View File

@@ -2,13 +2,20 @@
FUSD: A Linux Framework for User-Space Devices
----------------------------------------------
Welcome to FUSD!
**Welcome to FUSD!**
This is FUSD snapshot 20070111, released 11 January 2007. You can get
the most recent source, along with online documentation, from xiph.org
SVN:
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)
http://svn.xiph.org/trunk/fusd
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.
The official URL for this fork is:
http://github.com/Godzil/fusd
There is extensive documentation available in the 'doc' directory.
The FUSD User Manual is available in PDF, Postscript, and HTML format.
@@ -17,7 +24,7 @@ it is fully updated, it may not cover all features that exist in the
current version of fusd.
FUSD is free and open source software, released under a BSD-style
license. See the file 'LICENSE' for details.
license. See the file 'LICENSE' for details.
QUICK START GUIDE
@@ -25,81 +32,81 @@ QUICK START GUIDE
Instructions for the impatient:
1- Make sure you're using a system running Linux 2.6.x with udev; this
version of fusd is incompatable with the now-deprecated devfs. If the
1. Make sure you're using a system running Linux 2.6.x with udev; this
version of fusd is incompatable with the now-deprecated devfs. If the
kernel is a packaged version from a distribution, also verify any
optional packages needed for building new kernel modules are also
installed.
2- 'make ; make install' builds everything including examples, then
2. 'make ; make install' builds everything including examples, then
installs the libraries, includes and kernel module.
3- Update the udev configuration (usually in /etc/udev/rules.d/) to
3. Update the udev configuration (usually in /etc/udev/rules.d/) to
include the following rule:
# fusd device
SUBSYSTEM=="fusd", NAME="fusd/%k"
fusd device
SUBSYSTEM=="fusd", NAME="fusd/%k"
After updating, restart udevd (skill udevd; udevd -d).
After updating, restart udevd (skill udevd; udevd -d).
4- Insert the FUSD kernel module (modprobe kfusd)
4. Insert the FUSD kernel module (`modprobe kfusd`)
5- Verify the fusd devices /dev/fusd/status and /dev/fusd/control
exist. If the modprobe succeeds but no fusd devices appear,
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
successfully. The kfusd kernel module must be inserted after udev has
successfully. The kfusd kernel module must be inserted after udev has
been correctly configured and restarted.
6- Try running the helloworld example program (examples/helloworld).
When helloworld is running, 'cat /dev/helloworld' should return
'Hello, world!'.
6. Try running the `helloworld` example program (examples/helloworld).
When helloworld is running, `cat /dev/helloworld` should return
`Hello, world!`.
7- For more information, read the User's Manual in the 'doc' directory.
7. For more information, read the User's Manual in the 'doc' directory.
WHAT IS FUSD?
=============
FUSD (pronounced "fused") is a Linux framework for proxying device
file callbacks into user-space, allowing device files to be
implemented by daemons instead of kernel code. Despite being
implemented by daemons instead of kernel code. Despite being
implemented in user-space, FUSD devices can look and act just like any
other file under /dev which is implemented by kernel callbacks.
A user-space device driver can do many of the things that kernel
drivers can't, such as perform a long-running computation, block while
waiting for an event, or read files from the file system. Unlike
waiting for an event, or read files from the file system. Unlike
kernel drivers, a user-space device driver can use other device
drivers--that is, access the network, talk to a serial port, get
interactive input from the user, pop up GUI windows, or read from
disks. User-space drivers implemented using FUSD can be much easier to
disks. User-space drivers implemented using FUSD can be much easier to
debug; it is impossible for them to crash the machine, are easily
traceable using tools such as gdb, and can be killed and restarted
without rebooting. FUSD drivers don't have to be in C--Perl, Python,
without rebooting. FUSD drivers don't have to be in C--Perl, Python,
or any other language that knows how to read from and write to a file
descriptor can work with FUSD. User-space drivers can be swapped out,
descriptor can work with FUSD. User-space drivers can be swapped out,
whereas kernel drivers lock physical memory.
FUSD drivers are conceptually similar to kernel drivers: a set of
callback functions called in response to system calls made on file
descriptors by user programs. FUSD's C library provides a device
descriptors by user programs. FUSD's C library provides a device
registration function, similar to the kernel's devfs_register_chrdev()
function, to create new devices. fusd_register() accepts the device
name and a structure full of pointers. Those pointers are callback
function, to create new devices. fusd_register() accepts the device
name and a structure full of pointers. Those pointers are callback
functions which are called in response to certain user system
calls--for example, when a process tries to open, close, read from, or
write to the device file. The callback functions should conform to
the standard definitions of POSIX system call behavior. In many ways,
write to the device file. The callback functions should conform to
the standard definitions of POSIX system call behavior. In many ways,
the user-space FUSD callback functions are identical to their kernel
counterparts.
The proxying of kernel system calls that makes this kind of program
possible is implemented by FUSD, using a combination of a kernel
module and cooperating user-space library. The kernel module
module and cooperating user-space library. The kernel module
implements a character device, /dev/fusd, which is used as a control
channel between the two. fusd_register() uses this channel to send a
channel between the two. fusd_register() uses this channel to send a
message to the FUSD kernel module, telling the name of the device the
user wants to register. The kernel module, in turn, registers that
device with the kernel proper using devfs. devfs and the kernel don't
user wants to register. The kernel module, in turn, registers that
device with the kernel proper using devfs. devfs and the kernel don't
know anything unusual is happening; it appears from their point of
view that the registered devices are simply being implemented by the
FUSD module.
@@ -107,22 +114,22 @@ FUSD module.
Later, when kernel makes a callback due to a system call (e.g. when
the character device file is opened or read), the FUSD kernel module's
callback blocks the calling process, marshals the arguments of the
callback into a message and sends it to user-space. Once there, the
callback into a message and sends it to user-space. Once there, the
library half of FUSD unmarshals it and calls whatever user-space
callback the FUSD driver passed to fusd_register(). When that
callback the FUSD driver passed to fusd_register(). When that
user-space callback returns a value, the process happens in reverse:
the return value and its side-effects are marshaled by the library
and sent to the kernel. The FUSD kernel module unmarshals this
and sent to the kernel. The FUSD kernel module unmarshals this
message, matches it up with a corresponding outstanding request, and
completes the system call. The calling process is completely unaware
completes the system call. The calling process is completely unaware
of this trickery; it simply enters the kernel once, blocks, unblocks,
and returns from the system call---just as it would for any other
blocking call.
One of the primary design goals of FUSD is stability. It should
One of the primary design goals of FUSD is stability. It should
not be possible for a FUSD driver to corrupt or crash the kernel,
either due to error or malice. Of course, a buggy driver itself may
corrupt itself (e.g., due to a buffer overrun). However, strict error
either due to error or malice. Of course, a buggy driver itself may
corrupt itself (e.g., due to a buffer overrun). However, strict error
checking is implemented at the user-kernel boundary which should
prevent drivers from corrupting the kernel or any other user-space
process---including the errant driver's own clients, and other FUSD
@@ -130,10 +137,14 @@ drivers.
For more information, please see the comprehensive documentation in
the 'doc' directory.
> Jeremy Elson <jelson@circlemud.org> <br>
> August 19, 2003 <br>
Jeremy Elson <jelson@circlemud.org>
August 19, 2003
> updated,<br>
> Monty <monty@xiph.org> <br>
> January 11, 2007 <br>
updated,
Monty <monty@xiph.org>
January 11, 2007
> Updated, <br>
> Godzil <godzil@godzil.net> <br>
> March 01, 2011 / January 18, 2012 (public release on github)

View File

@@ -1,13 +1,10 @@
default: docs
clean:
@rm -f *.[ch].example
rm -f *.[ch].example
rm -f fusd.dvi
examples:
@rm -f *.[ch].example
@./make-examples.pl ../examples/*.[ch]
docs: examples
docs:
latex fusd
latex fusd

View File

@@ -1,50 +0,0 @@
#!/usr/bin/perl -w
foreach $path (@ARGV) {
$writing = 0;
if (!open(IN, $path)) {
print "trying to open $path: $!\n";
next;
}
while ($line = <IN>) {
if ($line =~ /EXAMPLE (\w*) ([\w\-\.]*)/) {
$command = $1;
$filename = $2 . ".example";
if ($command eq 'START') {
if ($writing == 0) {
if (!open(OUT, ">>$filename")) {
print "trying to write to $filename: $!\n";
} else {
print "$path: writing to $filename\n";
$writing = 1;
}
} else {
print "$path: got $line while already writing!\n";
}
}
if ($command eq 'STOP') {
if ($writing == 1) {
close(OUT);
$writing = 0;
} else {
chomp($line);
die "$path line $.: got $line when not writing!\n";
}
}
} else {
if ($writing && $line !~ /SKIPLINE/) {
print OUT $line;
}
}
}
if ($writing) {
close(OUT);
}
close(IN);
}

24
examples/Makefile Normal file
View File

@@ -0,0 +1,24 @@
SRC = console-read.c drums3.c echo.c helloworld.c logring.c pager.c\
drums2.c drums.c ioctl.c uid-filter.c
OBJ = console-read.o drums3.o echo.o helloworld.o logring.o pager.o\
drums2.o drums.o ioctl.o uid-filter.o
TARGETS = console-read drums3 echo helloworld logring pager\
drums2 drums ioctl uid-filter
default: $(TARGETS)
install: $(TARGETS)
clean:
rm -f *.o *.d $(TARGETS) gmon.out *~
$(TARGETS): %: %.c
$(CC) $(GCF) $< -o $@ ../libfusd/libfusd.a
%.d: %.c
$(CC) -M $(CFLAGS) $< > $@.$$$$; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$
ifeq ($(MAKECMDGOALS),target)
include $(SRC:.c=.d)
endif

View File

@@ -40,7 +40,7 @@
* need a template from which to start on a real driver, use pager.c
* instead.
*
* $Id: console-read.c,v 1.4 2003/07/11 22:29:38 cerpa Exp $
* $Id: console-read.c 12351 2007-01-19 07:22:54Z xiphmont $
*/
#include <stdio.h>
@@ -57,7 +57,7 @@ int do_open_or_close(struct fusd_file_info *file)
}
/* EXAMPLE START console-read.c */
int do_read(struct fusd_file_info *file, char *user_buffer,
ssize_t do_read(struct fusd_file_info *file, char *user_buffer,
size_t user_length, loff_t *offset)
{
char buf[128];
@@ -88,7 +88,7 @@ int main(int argc, char *argv[])
read: do_read,
close: do_open_or_close };
if (fusd_register("/dev/console-read", "misc", "console-read", 0666, NULL, &fops) < 0)
if (fusd_register("/dev/console-read", "test", "console-read", 0666, NULL, &fops) < 0)
perror("Unable to register device");
else {
printf("/dev/console-read should now exist - calling fusd_run...\n");

View File

@@ -42,7 +42,7 @@
* directory: /dev/drums/bam, /dev/drums/bum, etc. If you cat one of
* these devices, it returns a string that's the same as its name.
*
* $Id: drums.c,v 1.4 2003/07/11 22:29:38 cerpa Exp $
* $Id: drums.c 12355 2007-01-19 17:44:17Z xiphmont $
*/
#include <stdio.h>
@@ -59,7 +59,7 @@
static char *drums_strings[] = {"bam", "bum", "beat", "boom",
"bang", "crash", NULL};
int drums_read(struct fusd_file_info *file, char *user_buffer,
ssize_t drums_read(struct fusd_file_info *file, char *user_buffer,
size_t user_length, loff_t *offset)
{
int len;

View File

@@ -47,7 +47,7 @@
* to remember if this user has read before; cat /dev/drums/X will
* read infinitely
*
* $Id: drums2.c,v 1.6 2003/07/11 22:29:38 cerpa Exp $
* $Id: drums2.c 12355 2007-01-19 17:44:17Z xiphmont $
*/
#include <stdio.h>
@@ -82,14 +82,16 @@ int drums_open(struct fusd_file_info *file)
/* file->device_info is what we passed to fusd_register when we
* registered the device. It's a pointer into the "drums" struct. */
struct drum_info *d = (struct drum_info *) file->device_info;
int *user_num = calloc(1, sizeof(*user_num));
/* Store this user's unique user number in their private_data */
file->private_data = (void *) ++(d->num_users);
*user_num = ++(d->num_users);
file->private_data = (void *) user_num;
return 0; /* return success */
}
int drums_read(struct fusd_file_info *file, char *user_buffer,
ssize_t drums_read(struct fusd_file_info *file, char *user_buffer,
size_t user_length, loff_t *offset)
{
struct drum_info *d = (struct drum_info *) file->device_info;
@@ -97,10 +99,11 @@ int drums_read(struct fusd_file_info *file, char *user_buffer,
char sound[128];
sprintf(sound, "You are user %d to hear a drum go '%s'!\n",
(int) file->private_data, d->name);
*(int *) file->private_data, d->name);
len = MIN(user_length, strlen(sound));
memcpy(user_buffer, sound, len);
*offset += len;
return len;
}
/* EXAMPLE STOP */

View File

@@ -43,7 +43,7 @@
* However, it also prints a prompt to the console, asking the user if
* how loud the drums should be.
*
* $Id: drums3.c,v 1.3 2003/07/11 22:29:38 cerpa Exp $
* $Id: drums3.c 12351 2007-01-19 07:22:54Z xiphmont $
*/
#include <stdio.h>
@@ -63,7 +63,7 @@ static char *drums_strings[] = {"bam", "bum", "beat", "boom",
int volume = 2; /* default volume is 2 */
int drums_read(struct fusd_file_info *file, char *user_buffer,
ssize_t drums_read(struct fusd_file_info *file, char *user_buffer,
size_t user_length, loff_t *offset)
{
int len;

View File

@@ -41,7 +41,7 @@
* stored. Then, when you read (e.g. "cat /dev/echo"), you get back
* whatever you wrote most recently.
*
* $Id: echo.c,v 1.6 2003/07/11 22:29:38 cerpa Exp $
* $Id: echo.c 12351 2007-01-19 07:22:54Z xiphmont $
*/
#include <stdio.h>
@@ -58,7 +58,7 @@
char *data = NULL;
int data_length = 0;
int echo_read(struct fusd_file_info *file, char *user_buffer,
ssize_t echo_read(struct fusd_file_info *file, char *user_buffer,
size_t user_length, loff_t *offset)
{
/* if the user has read past the end of the data, return EOF */

Binary file not shown.

View File

@@ -37,7 +37,7 @@
* hello-world: Simply creates a device called /dev/hello-world, which
* greets you when you try to get it.
*
* $Id: helloworld.c,v 1.11 2003/07/11 22:29:38 cerpa Exp $
* $Id: helloworld.c 12351 2007-01-19 07:22:54Z xiphmont $
*/
/* EXAMPLE START helloworld.c */

View File

@@ -41,7 +41,7 @@
* the other examples, anyway), because this program is both an
* example and part of the regression test suite.
*
* $Id: ioctl.c,v 1.4 2003/07/11 22:29:39 cerpa Exp $
* $Id: ioctl.c 12351 2007-01-19 07:22:54Z xiphmont $
*/
#include <stdio.h>
@@ -115,8 +115,9 @@ int do_ioctl(struct fusd_file_info *file, int cmd, void *arg)
case IOCTL_TEST1:
case IOCTL_TEST2:
printf("ioctl server: got test1/2, arg=%d, returning it\n", (int) arg);
return (int) arg;
printf("ioctl server: got test1/2, arg=%p, *arg= %d, returning it\n",
arg, *(int *)arg);
return *(int *) arg;
break;
/* EXAMPLE START ioctl-server.c */
@@ -185,7 +186,8 @@ int main(int argc, char *argv[])
/* ioctl server */
struct fusd_file_operations f = { open: zeroreturn, close: zeroreturn,
ioctl: do_ioctl};
if (fusd_register("ioctltest", 0666, NULL, &f) < 0)
if (fusd_register("/dev/ioctltest", "misc", "ioctltest",
0666, NULL, &f) < 0)
perror("registering ioctltest");
printf("server starting\n");
fusd_run();
@@ -216,18 +218,24 @@ int main(int argc, char *argv[])
CHECK(ret == 0);
/* test1: issue a command with a simple (integer) argument */
ret = ioctl(fd, IOCTL_TEST1, TEST1_NUM);
CHECK(ret == TEST1_NUM);
CHECK(errno == 0);
printf("ioctl test1: got %d, errno=%d (expecting %d, errno=0)\n\n",
ret, errno, TEST1_NUM);
{
int arg = TEST1_NUM;
ret = ioctl(fd, IOCTL_TEST1, &arg);
CHECK(ret == TEST1_NUM);
CHECK(errno == 0);
printf("ioctl test1: got %d, errno=%d (expecting %d, errno=0)\n\n",
ret, errno, TEST1_NUM);
}
/* test2 again: make sure errno is set properly */
ret = ioctl(fd, IOCTL_TEST2, -ELIBBAD);
CHECK(errno == ELIBBAD);
CHECK(ret == -1);
printf("ioctl test2: got %d, errno=%d (expecting -1, errno=%d)\n\n",
ret, errno, ELIBBAD);
{
int arg = -ELIBBAD;
ret = ioctl(fd, IOCTL_TEST2, &arg);
CHECK(errno == ELIBBAD);
CHECK(ret == -1);
printf("ioctl test2: got %d, errno=%d (expecting -1, errno=%d)\n\n",
ret, errno, ELIBBAD);
}
printf("ioctl test3: expecting retval 0, string This Is Test3\n");
/* EXAMPLE START ioctl-client.c */

View File

@@ -71,7 +71,7 @@
* but want to use it on a system that does not have FUSD, check out
* emlog at http://www.circlemud.org/~jelson/software/emlog.
*
* $Id: logring.c,v 1.8 2003/07/11 22:29:39 cerpa Exp $
* $Id: logring.c 12351 2007-01-19 07:22:54Z xiphmont $
*/
#include <stdio.h>
@@ -340,7 +340,7 @@ void logring_complete_polldiff(struct logring_client *c)
* may come from the kernel before the driver has returned the first
* one; if this happens, use fusd_destroy() to get rid of the older one.
*/
ssize_t logring_polldiff(struct fusd_file_info *file, unsigned int flags)
int logring_polldiff(struct fusd_file_info *file, unsigned int flags)
{
struct logring_client *c = (struct logring_client *) file->private_data;

View File

@@ -60,7 +60,7 @@
* If you close the FD and then reopen it, there will be a race (pages
* that arrive between the close and open will not be delivered).
*
* $Id: pager.c,v 1.9 2003/07/11 22:29:39 cerpa Exp $
* $Id: pager.c 12355 2007-01-19 17:44:17Z xiphmont $
*/
#include <stdio.h>
@@ -247,7 +247,7 @@ void pager_notify_complete_read(struct pager_client *c)
* one; if this happens, use fusd_destroy() to get rid of the older one.
*/
/* EXAMPLE START pager-polldiff.c */
ssize_t pager_notify_polldiff(struct fusd_file_info *file,
int pager_notify_polldiff(struct fusd_file_info *file,
unsigned int cached_state)
{
struct pager_client *c = (struct pager_client *) file->private_data;

View File

@@ -42,7 +42,7 @@
* not be read by anyone other than the driver owner (not even root!).
* When you read from the device, it returns your PID to you.
*
* $Id: uid-filter.c,v 1.4 2003/07/11 22:29:39 cerpa Exp $
* $Id: uid-filter.c 12351 2007-01-19 07:22:54Z xiphmont $
*/
#include <stdio.h>
@@ -71,7 +71,7 @@ int do_open(struct fusd_file_info *file)
return 0;
}
int do_read(struct fusd_file_info *file, char *user_buffer,
ssize_t do_read(struct fusd_file_info *file, char *user_buffer,
size_t user_length, loff_t *offset)
{
char buf[128];

View File

@@ -37,28 +37,29 @@
*
* Private header file used by the Linux Kernel Module
*
* $Id: kfusd.h,v 1.41 2003/07/11 22:29:39 cerpa Exp $
* $Id: kfusd.h 12351 2007-01-19 07:22:54Z xiphmont $
*/
#ifndef __KFUSD_H__
#define __KFUSD_H__
# define __KFUSD_H__
#include "fusd_msg.h"
# include "fusd_msg.h"
# include <linux/version.h>
/* magic numbers for structure checking; unique w.r.t
* /usr/src/linux/Documentation/magic-number.txt */
#define FUSD_DEV_MAGIC 0x8b43a123
#define FUSD_FILE_MAGIC 0x613aa8fe
# define FUSD_DEV_MAGIC 0x8b43a123
# define FUSD_FILE_MAGIC 0x613aa8fe
/* number of devices that can be created with fusd */
#define MAX_FUSD_DEVICES 128
# define MAX_FUSD_DEVICES 128
/* number of times each device can be opened simultaneously */
#define MIN_FILEARRAY_SIZE 8 /* initialize allocation */
#define MAX_FILEARRAY_SIZE 1024 /* maximum it can grow to */
# define MIN_FILEARRAY_SIZE 8 /* initialize allocation */
# define MAX_FILEARRAY_SIZE 1024 /* maximum it can grow to */
/* maximum read/write size we're willing to service */
#define MAX_RW_SIZE (1024*128)
# define MAX_RW_SIZE (1024*128)
/********************** Structure Definitions *******************************/
@@ -88,7 +89,7 @@ struct fusd_transaction
struct fusd_dev_t_s;
typedef struct fusd_dev_t_s fusd_dev_t;
struct CLASS;
struct class_device;
struct device;
/* state kept per opened file (i.e., an instance of a device) */
typedef struct {
@@ -121,16 +122,18 @@ struct fusd_dev_t_s {
struct task_struct* task;
char *name; /* Name of the device under devfs (/dev) */
char *class_name;
char *dev_name;
struct CLASS *clazz;
int owns_class;
struct class_device *class_device;
char *class_name;
char *dev_name;
struct CLASS *clazz;
int owns_class;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
struct class_device *device;
#else
struct device *device;
#endif
void *private_data; /* User's private data */
struct cdev* handle;
dev_t dev_id;
// devfs_handle_t handle; /* The devfs-provided handle */
struct cdev* handle;
dev_t dev_id;
fusd_file_t **files; /* Array of this device's open files */
int array_size; /* Size of the array pointed to by 'files' */
@@ -175,34 +178,34 @@ STATIC struct fusd_transaction* fusd_find_transaction_by_pid(fusd_file_t *fusd_f
/**** Utility functions & macros ****/
#ifdef CONFIG_FUSD_USE_WAKEUPSYNC
#define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible_sync(x)
#else
#define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible(x)
#endif /* CONFIG_FUSD_USE_WAKEUPSYNC */
# ifdef CONFIG_FUSD_USE_WAKEUPSYNC
# define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible_sync(x)
# else
# define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible(x)
# endif /* CONFIG_FUSD_USE_WAKEUPSYNC */
#ifdef CONFIG_FUSD_DEBUG
# ifdef CONFIG_FUSD_DEBUG
static void rdebug_real(char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
#define RDEBUG(message_level, args...) do { \
# define RDEBUG(message_level, args...) do { \
if (fusd_debug_level >= message_level) rdebug_real(args); \
} while(0)
#else
#define RDEBUG(message_level, args...)
#endif /* CONFIG_FUSD_DEBUG */
# else
# define RDEBUG(message_level, args...)
# endif /* CONFIG_FUSD_DEBUG */
#define ZOMBIE(fusd_dev) ((fusd_dev)->zombie)
# define ZOMBIE(fusd_dev) ((fusd_dev)->zombie)
#define GET_FUSD_DEV(candidate, fusd_dev) do { \
# define GET_FUSD_DEV(candidate, fusd_dev) do { \
fusd_dev = candidate; \
if (fusd_dev == NULL || fusd_dev->magic != FUSD_DEV_MAGIC) \
goto invalid_dev; \
} while (0)
#define GET_FUSD_FILE_AND_DEV(candidate, fusd_file, fusd_dev) do { \
# define GET_FUSD_FILE_AND_DEV(candidate, fusd_file, fusd_dev) do { \
fusd_file = candidate; \
if (fusd_file == NULL || fusd_file->magic != FUSD_FILE_MAGIC) \
goto invalid_file; \
@@ -211,36 +214,40 @@ static void rdebug_real(char *fmt, ...)
goto invalid_file; \
} while (0)
#define LOCK_FUSD_DEV(fusd_dev) \
# define LOCK_FUSD_DEV(fusd_dev) \
do { down(&fusd_dev->dev_sem); \
if (ZOMBIE(fusd_dev)) { up(&fusd_dev->dev_sem); goto zombie_dev; } \
} while (0)
/* rawlock does not do a zombie check */
#define RAWLOCK_FUSD_DEV(fusd_dev) \
# define RAWLOCK_FUSD_DEV(fusd_dev) \
do { down(&fusd_dev->dev_sem); } while (0)
#define UNLOCK_FUSD_DEV(fusd_dev) \
# define UNLOCK_FUSD_DEV(fusd_dev) \
do { up(&fusd_dev->dev_sem); } while (0)
#define LOCK_FUSD_FILE(fusd_file) \
# define LOCK_FUSD_FILE(fusd_file) \
do { down(&fusd_file->file_sem); \
} while (0)
#define UNLOCK_FUSD_FILE(fusd_file) \
# define UNLOCK_FUSD_FILE(fusd_file) \
do { up(&fusd_file->file_sem); } while (0)
#define FREE_FUSD_MSGC(fusd_msgc) do { \
# define FREE_FUSD_MSGC(fusd_msgc) do { \
if ((fusd_msgc)->fusd_msg.data != NULL) VFREE(fusd_msgc->fusd_msg.data); \
KFREE(fusd_msgc); \
} while (0)
#define NAME(fusd_dev) ((fusd_dev)->name == NULL ? \
# define FREE_FUSD_MSGC(fusd_msgc) do { \
if ((fusd_msgc)->fusd_msg.data != NULL) VFREE(fusd_msgc->fusd_msg.data); \
KFREE(fusd_msgc); \
} while (0)
# define NAME(fusd_dev) ((fusd_dev)->name == NULL ? \
"<noname>" : (fusd_dev)->name)
#ifdef CONFIG_FUSD_MEMDEBUG
# ifdef CONFIG_FUSD_MEMDEBUG
static int fusd_mem_init(void);
static void fusd_mem_cleanup(void);
static void fusd_mem_add(void *ptr, int line, int size);
@@ -249,25 +256,28 @@ static void *fusd_kmalloc(size_t size, int type, int line);
static void fusd_kfree(void *ptr);
static void *fusd_vmalloc(size_t size, int line);
static void fusd_vfree(void *ptr);
# define KMALLOC(size, type) fusd_kmalloc(size, type, __LINE__)
# define KFREE(ptr) fusd_kfree(ptr)
# define VMALLOC(size) fusd_vmalloc(size, __LINE__)
# define VFREE(ptr) fusd_vfree(ptr)
#else /* no memory debugging */
# define KMALLOC(size, type) kmalloc(size, type)
# define KFREE(ptr) kfree(ptr)
# define KMALLOC(size, type) fusd_kmalloc(size, type, __LINE__)
# define KFREE(ptr) fusd_kfree(ptr)
# define VMALLOC(size) fusd_vmalloc(size, __LINE__)
# define VFREE(ptr) fusd_vfree(ptr)
# else /* no memory debugging */
# define KMALLOC(size, type) kmalloc(size, type)
# define KFREE(ptr) kfree(ptr)
/*# define VMALLOC(size) vmalloc(size)*/
# define VMALLOC(size) kmalloc(size, GFP_KERNEL)
# define VFREE(ptr) kfree(ptr)
#endif /* CONFIG_FUSD_MEMDEBUG */
# define VMALLOC(size) kmalloc(size, GFP_KERNEL)
# define VFREE(ptr) kfree(ptr)
# endif /* CONFIG_FUSD_MEMDEBUG */
/* Functions like this should be in the kernel, but they are not. Sigh. */
#ifdef CONFIG_SMP
# ifdef CONFIG_SMP
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
DECLARE_MUTEX(atomic_ops);
#else
DEFINE_SEMAPHORE(atomic_ops);
#endif
static __inline__ int atomic_inc_and_ret(int *i)
{
int val;
@@ -277,12 +287,11 @@ static __inline__ int atomic_inc_and_ret(int *i)
up(&atomic_ops);
return val;
}
#else
# else
static __inline__ int atomic_inc_and_ret(int *i)
{
return (++(*i));
}
#endif
# endif
#endif /* __KFUSD_H__ */

View File

@@ -1,16 +1,21 @@
ifneq ($(KERNELRELEASE),)
obj-m := kfusd.o
KERNEL_VER ?= $(KERNELRELEASE)
else
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
ROOTFS ?=
KERNEL_VER ?= 2.6.32.7
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) EXTRA_CFLAGS=-I$(PWD)/../include modules
install:
$(INSTALL) -d -m 0755 /lib/modules/$(shell uname -r)/kernel/drivers/misc
$(INSTALL) -m 0755 kfusd.ko /lib/modules/$(shell uname -r)/kernel/drivers/misc
/sbin/depmod -a
install:
install -d -m 0755 $(ROOTFS)/lib/modules/$(KERNEL_VER)/kernel/drivers/misc
install -m 0755 kfusd.ko $(ROOTFS)/lib/modules/$(KERNEL_VER)/kernel/drivers/misc
# /sbin/depmod -a
clean:
rm -f .kfusd* Modules.symvers \

File diff suppressed because it is too large Load Diff

View File

@@ -35,10 +35,10 @@
*
* authors: jelson and girod
*
* $Id: libfusd.c,v 1.61 2003/07/11 22:29:39 cerpa Exp $
* $Id: libfusd.c 12351 2007-01-19 07:22:54Z xiphmont $
*/
char libfusd_c_id[] = "$Id: libfusd.c,v 1.61 2003/07/11 22:29:39 cerpa Exp $";
char libfusd_c_id[] = "$Id: libfusd.c 12351 2007-01-19 07:22:54Z xiphmont $";
#include <stdio.h>
#include <stdlib.h>
@@ -328,8 +328,6 @@ void fusd_fdset_add(fd_set *set, int *max)
}
}
/*
* fusd_dispatch_fdset: given an fd_set full of descriptors, call
* fusd_dispatch on every descriptor in the set which is a valid FUSD
@@ -410,16 +408,21 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
/* dispatch on operation type */
user_retval = -ENOSYS;
//printf("dispatch_one: subcmd: %d - ", 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) {
@@ -433,11 +436,13 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
}
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)
{
user_retval = fops->mmap(file, msg->parm.fops_msg.offset, msg->parm.fops_msg.length, msg->parm.fops_msg.flags,
@@ -445,6 +450,7 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
}
break;
case FUSD_IOCTL:
//printf("FUSD_IOCTL\n");
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
@@ -466,6 +472,7 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
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)
@@ -473,6 +480,7 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
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);
@@ -533,6 +541,7 @@ void fusd_dispatch(int fd)
if (!FUSD_FD_VALID(fd)) {
errno = EBADF;
retval = -1;
fprintf(stderr, "libfusd: not a valid FUSD FD\n");
goto out;
}
fops = FUSD_GET_FOPS(fd);
@@ -555,7 +564,7 @@ void fusd_dispatch(int fd)
out:
if (retval < 0 && errno != EPIPE)
fprintf(stderr, "libfusd: fusd_dispatch error on fd %d: %m\n", fd);
fprintf(stderr, "libfusd: fusd_dispatch error on fd %d: [%d] %m \n", fd, retval);
}
@@ -648,11 +657,16 @@ int fusd_return(fusd_file_info_t *file, ssize_t retval)
/* send message to kernel */
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 {
driver_retval = write(fd, msg, sizeof(fusd_msg_t));

View File

@@ -1,149 +0,0 @@
# auto-dependency generation makefile
#### Default values
SRCEXTENSIONS := c C cpp
CC := gcc
CPP := g++
LD := ld
AR := ar
#### build object directory token
CPU := $(shell uname -m)
OS := $(shell uname -s | tr '[A-Z]' '[a-z]')
DEFAULT_ARCH := $(CPU)-$(OS)
ifeq ($(strip $(ARCH)),)
ARCH := $(DEFAULT_ARCH)
endif
OBJTOKEN := obj.$(ARCH)
#
# Under most circumstances, paths are simple
#
ifeq ($(POSTROOT),..)
MODPATH := .
OBJDIR := $(OBJTOKEN)
else
MODPATH := $(POSTROOT)/$(MODULENAME)
OBJDIR := $(MODPATH)/$(OBJTOKEN)
endif
#
# Directories
#
MODLIBS := \
-L$(OBJDIR) \
$(foreach dir, $(MODULES), -L$(POSTROOT)/$(dir)/$(OBJTOKEN))
MODINCLUDES := \
-I$(MODPATH)/include \
$(foreach dir, $(MODULES), -I$(POSTROOT)/$(dir)/include)
ALLTARGETS := \
$(foreach targ, $(TARGETS), $(OBJDIR)/$(targ))
VPATH := \
$(MODPATH)/include \
$(foreach dir, $(SRCDIRS), $(MODPATH)/$(dir)) \
$(foreach dir, $(MODULES), $(POSTROOT)/$(dir)/include)
#### include paths
LIBPATH := $(MODLIBS)
INCLUDEPATH += -I. -Iinclude $(MODINCLUDES)
KCFLAGS = -O2 \
-Wall -Werror -Wstrict-prototypes \
-fno-strict-aliasing -fomit-frame-pointer \
-DMODULE -D__KERNEL__
CFLAGS := -fPIC -Wall -O2 -g
CCFLAGS := -Werror
CPPFLAGS := -ftemplate-depth-30
#### Architecture deps
KERNEL_INCLUDE := $(KERNEL_HOME)/include
BINSTRIP := strip
KCFLAGS += $(INCLUDEPATH)
CFLAGS += $(INCLUDEPATH) $(LIBPATH)
CCFLAGS += $(CFLAGS)
CPPFLAGS += $(CFLAGS)
#
# targets
#
default: $(ALLTARGETS)
####################################################
#
# Dependency generation
#
# Get list of all source files
SOURCES := \
$(notdir $(wildcard \
$(foreach dir, $(SRCDIRS), \
$(foreach ext, $(SRCEXTENSIONS), $(dir)/*.$(ext)))))
# Convert all .c, .cpp, .C to .d
SRC_AND_DEPENDS := $(foreach ext, $(SRCEXTENSIONS),\
$(patsubst %.$(ext),%.d,$(SOURCES)))
DEPENDS := $(foreach file, $(filter %.d,$(SRC_AND_DEPENDS)), $(OBJDIR)/$(file))
BASE = $(subst /,\/,$*)
ODIR = $(subst /,\/,$(OBJDIR))
# This magic is from the 'make' manual (with mods by jelson)
$(OBJDIR)/%.d: %.c
@mkdir -p $(OBJDIR)
set -e; $(CC) -MM -I$(KERNEL_INCLUDE) $(CFLAGS) $< \
| sed 's/\($(BASE)\)\.o[ :]*/$(ODIR)\/$(BASE).o $(ODIR)\/$(BASE).d : /g' > $@; \
[ -s $@ ] || rm -f $@
$(OBJDIR)/%.d: %.C
@mkdir -p $(OBJDIR)
set -e; $(CC) -MM $(CPPFLAGS) $< \
| sed 's/\($(BASE)\)\.o[ :]*/$(ODIR)\/$(BASE).o $(ODIR)\/$(BASE).d : /g' > $@; \
[ -s $@ ] || rm -f $@
$(OBJDIR)/%.d: %.cpp
@mkdir -p $(OBJDIR)
set -e; $(CC) -MM $(CPPFLAGS) $< \
| sed 's/\($(BASE)\)\.o[ :]*/$(ODIR)\/$(BASE).o $(ODIR)\/$(BASE).d : /g' > $@; \
[ -s $@ ] || rm -f $@
#
# Rules
#
$(OBJDIR)/%.o: %.cpp
$(CPP) $(CPPFLAGS) $< -c -o $@
$(OBJDIR)/%.o: %.C
$(CPP) $(CPPFLAGS) $< -c -o $@
$(OBJDIR)/%.o: %.c
$(CC) $(CCFLAGS) $< -c -o $@
clean:
rm -f $(ALLTARGETS) $(OBJDIR)/*.[oa] $(OBJDIR)/*.so.* $(DEPENDS)
include $(DEPENDS)