Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd9d3e1df3 | ||
|
|
cc3e84dfbf | ||
|
|
0bf42c8088 | ||
|
|
41185bd56b | ||
|
|
55b0389911 | ||
|
|
243da80fc6 | ||
|
|
48511c545d | ||
|
|
0922adc0b1 | ||
|
|
5880dc8fe1 |
5
Makefile
5
Makefile
@@ -23,16 +23,19 @@ export
|
|||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
|
|
||||||
SUBDIRS = kfusd libfusd
|
SUBDIRS = kfusd libfusd examples
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$(MAKE) -C libfusd
|
$(MAKE) -C libfusd
|
||||||
$(MAKE) -C kfusd
|
$(MAKE) -C kfusd
|
||||||
|
$(MAKE) -C examples
|
||||||
|
|
||||||
install:
|
install:
|
||||||
$(MAKE) -C libfusd install
|
$(MAKE) -C libfusd install
|
||||||
$(MAKE) -C kfusd install
|
$(MAKE) -C kfusd install
|
||||||
|
$(MAKE) -C examples install
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(MAKE) -C kfusd clean
|
$(MAKE) -C kfusd clean
|
||||||
$(MAKE) -C libfusd clean
|
$(MAKE) -C libfusd clean
|
||||||
|
$(MAKE) -C examples clean
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
default: docs
|
default: docs
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -f *.[ch].example
|
rm -f *.[ch].example
|
||||||
|
rm -f fusd.dvi
|
||||||
|
|
||||||
examples:
|
docs:
|
||||||
@rm -f *.[ch].example
|
|
||||||
@./make-examples.pl ../examples/*.[ch]
|
|
||||||
|
|
||||||
docs: examples
|
|
||||||
latex fusd
|
latex fusd
|
||||||
latex fusd
|
latex fusd
|
||||||
|
|
||||||
|
|||||||
@@ -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
24
examples/Makefile
Normal 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
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
* need a template from which to start on a real driver, use pager.c
|
* need a template from which to start on a real driver, use pager.c
|
||||||
* instead.
|
* instead.
|
||||||
*
|
*
|
||||||
* $Id: console-read.c,v 1.4 2003/07/11 22:29:38 cerpa Exp $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -57,7 +57,7 @@ int do_open_or_close(struct fusd_file_info *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* EXAMPLE START console-read.c */
|
/* 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)
|
size_t user_length, loff_t *offset)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@@ -88,7 +88,7 @@ int main(int argc, char *argv[])
|
|||||||
read: do_read,
|
read: do_read,
|
||||||
close: do_open_or_close };
|
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");
|
perror("Unable to register device");
|
||||||
else {
|
else {
|
||||||
printf("/dev/console-read should now exist - calling fusd_run...\n");
|
printf("/dev/console-read should now exist - calling fusd_run...\n");
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
* directory: /dev/drums/bam, /dev/drums/bum, etc. If you cat one of
|
* 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.
|
* 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$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
static char *drums_strings[] = {"bam", "bum", "beat", "boom",
|
static char *drums_strings[] = {"bam", "bum", "beat", "boom",
|
||||||
"bang", "crash", NULL};
|
"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)
|
size_t user_length, loff_t *offset)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
* to remember if this user has read before; cat /dev/drums/X will
|
* to remember if this user has read before; cat /dev/drums/X will
|
||||||
* read infinitely
|
* read infinitely
|
||||||
*
|
*
|
||||||
* $Id: drums2.c,v 1.6 2003/07/11 22:29:38 cerpa Exp $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#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
|
/* file->device_info is what we passed to fusd_register when we
|
||||||
* registered the device. It's a pointer into the "drums" struct. */
|
* registered the device. It's a pointer into the "drums" struct. */
|
||||||
struct drum_info *d = (struct drum_info *) file->device_info;
|
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 */
|
/* 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 */
|
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)
|
size_t user_length, loff_t *offset)
|
||||||
{
|
{
|
||||||
struct drum_info *d = (struct drum_info *) file->device_info;
|
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];
|
char sound[128];
|
||||||
|
|
||||||
sprintf(sound, "You are user %d to hear a drum go '%s'!\n",
|
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));
|
len = MIN(user_length, strlen(sound));
|
||||||
memcpy(user_buffer, sound, len);
|
memcpy(user_buffer, sound, len);
|
||||||
|
*offset += len;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
/* EXAMPLE STOP */
|
/* EXAMPLE STOP */
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
* However, it also prints a prompt to the console, asking the user if
|
* However, it also prints a prompt to the console, asking the user if
|
||||||
* how loud the drums should be.
|
* how loud the drums should be.
|
||||||
*
|
*
|
||||||
* $Id: drums3.c,v 1.3 2003/07/11 22:29:38 cerpa Exp $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -63,7 +63,7 @@ static char *drums_strings[] = {"bam", "bum", "beat", "boom",
|
|||||||
|
|
||||||
int volume = 2; /* default volume is 2 */
|
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)
|
size_t user_length, loff_t *offset)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
* stored. Then, when you read (e.g. "cat /dev/echo"), you get back
|
* stored. Then, when you read (e.g. "cat /dev/echo"), you get back
|
||||||
* whatever you wrote most recently.
|
* whatever you wrote most recently.
|
||||||
*
|
*
|
||||||
* $Id: echo.c,v 1.6 2003/07/11 22:29:38 cerpa Exp $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
char *data = NULL;
|
char *data = NULL;
|
||||||
int data_length = 0;
|
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)
|
size_t user_length, loff_t *offset)
|
||||||
{
|
{
|
||||||
/* if the user has read past the end of the data, return EOF */
|
/* if the user has read past the end of the data, return EOF */
|
||||||
|
|||||||
Binary file not shown.
@@ -37,7 +37,7 @@
|
|||||||
* hello-world: Simply creates a device called /dev/hello-world, which
|
* hello-world: Simply creates a device called /dev/hello-world, which
|
||||||
* greets you when you try to get it.
|
* greets you when you try to get it.
|
||||||
*
|
*
|
||||||
* $Id: helloworld.c,v 1.11 2003/07/11 22:29:38 cerpa Exp $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* EXAMPLE START helloworld.c */
|
/* EXAMPLE START helloworld.c */
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
* the other examples, anyway), because this program is both an
|
* the other examples, anyway), because this program is both an
|
||||||
* example and part of the regression test suite.
|
* example and part of the regression test suite.
|
||||||
*
|
*
|
||||||
* $Id: ioctl.c,v 1.4 2003/07/11 22:29:39 cerpa Exp $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -115,8 +115,9 @@ int do_ioctl(struct fusd_file_info *file, int cmd, void *arg)
|
|||||||
|
|
||||||
case IOCTL_TEST1:
|
case IOCTL_TEST1:
|
||||||
case IOCTL_TEST2:
|
case IOCTL_TEST2:
|
||||||
printf("ioctl server: got test1/2, arg=%d, returning it\n", (int) arg);
|
printf("ioctl server: got test1/2, arg=%p, *arg= %d, returning it\n",
|
||||||
return (int) arg;
|
arg, *(int *)arg);
|
||||||
|
return *(int *) arg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* EXAMPLE START ioctl-server.c */
|
/* EXAMPLE START ioctl-server.c */
|
||||||
@@ -185,7 +186,8 @@ int main(int argc, char *argv[])
|
|||||||
/* ioctl server */
|
/* ioctl server */
|
||||||
struct fusd_file_operations f = { open: zeroreturn, close: zeroreturn,
|
struct fusd_file_operations f = { open: zeroreturn, close: zeroreturn,
|
||||||
ioctl: do_ioctl};
|
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");
|
perror("registering ioctltest");
|
||||||
printf("server starting\n");
|
printf("server starting\n");
|
||||||
fusd_run();
|
fusd_run();
|
||||||
@@ -216,18 +218,24 @@ int main(int argc, char *argv[])
|
|||||||
CHECK(ret == 0);
|
CHECK(ret == 0);
|
||||||
|
|
||||||
/* test1: issue a command with a simple (integer) argument */
|
/* test1: issue a command with a simple (integer) argument */
|
||||||
ret = ioctl(fd, IOCTL_TEST1, TEST1_NUM);
|
{
|
||||||
CHECK(ret == TEST1_NUM);
|
int arg = TEST1_NUM;
|
||||||
CHECK(errno == 0);
|
ret = ioctl(fd, IOCTL_TEST1, &arg);
|
||||||
printf("ioctl test1: got %d, errno=%d (expecting %d, errno=0)\n\n",
|
CHECK(ret == TEST1_NUM);
|
||||||
ret, errno, 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 */
|
/* test2 again: make sure errno is set properly */
|
||||||
ret = ioctl(fd, IOCTL_TEST2, -ELIBBAD);
|
{
|
||||||
CHECK(errno == ELIBBAD);
|
int arg = -ELIBBAD;
|
||||||
CHECK(ret == -1);
|
ret = ioctl(fd, IOCTL_TEST2, &arg);
|
||||||
printf("ioctl test2: got %d, errno=%d (expecting -1, errno=%d)\n\n",
|
CHECK(errno == ELIBBAD);
|
||||||
ret, 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");
|
printf("ioctl test3: expecting retval 0, string This Is Test3\n");
|
||||||
/* EXAMPLE START ioctl-client.c */
|
/* EXAMPLE START ioctl-client.c */
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
* but want to use it on a system that does not have FUSD, check out
|
* but want to use it on a system that does not have FUSD, check out
|
||||||
* emlog at http://www.circlemud.org/~jelson/software/emlog.
|
* emlog at http://www.circlemud.org/~jelson/software/emlog.
|
||||||
*
|
*
|
||||||
* $Id: logring.c,v 1.8 2003/07/11 22:29:39 cerpa Exp $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#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
|
* 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.
|
* 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;
|
struct logring_client *c = (struct logring_client *) file->private_data;
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
* If you close the FD and then reopen it, there will be a race (pages
|
* 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).
|
* 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$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#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.
|
* one; if this happens, use fusd_destroy() to get rid of the older one.
|
||||||
*/
|
*/
|
||||||
/* EXAMPLE START pager-polldiff.c */
|
/* 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)
|
unsigned int cached_state)
|
||||||
{
|
{
|
||||||
struct pager_client *c = (struct pager_client *) file->private_data;
|
struct pager_client *c = (struct pager_client *) file->private_data;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
* not be read by anyone other than the driver owner (not even root!).
|
* 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.
|
* 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$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -71,7 +71,7 @@ int do_open(struct fusd_file_info *file)
|
|||||||
return 0;
|
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)
|
size_t user_length, loff_t *offset)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
*
|
*
|
||||||
* Private header file used by the Linux Kernel Module
|
* Private header file used by the Linux Kernel Module
|
||||||
*
|
*
|
||||||
* $Id: kfusd.h,v 1.41 2003/07/11 22:29:39 cerpa Exp $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __KFUSD_H__
|
#ifndef __KFUSD_H__
|
||||||
@@ -121,16 +121,15 @@ struct fusd_dev_t_s {
|
|||||||
struct task_struct* task;
|
struct task_struct* task;
|
||||||
|
|
||||||
char *name; /* Name of the device under devfs (/dev) */
|
char *name; /* Name of the device under devfs (/dev) */
|
||||||
char *class_name;
|
char *class_name;
|
||||||
char *dev_name;
|
char *dev_name;
|
||||||
struct CLASS *clazz;
|
struct CLASS *clazz;
|
||||||
int owns_class;
|
int owns_class;
|
||||||
struct class_device *class_device;
|
struct class_device *class_device;
|
||||||
|
|
||||||
void *private_data; /* User's private data */
|
void *private_data; /* User's private data */
|
||||||
struct cdev* handle;
|
struct cdev* handle;
|
||||||
dev_t dev_id;
|
dev_t dev_id;
|
||||||
// devfs_handle_t handle; /* The devfs-provided handle */
|
|
||||||
|
|
||||||
fusd_file_t **files; /* Array of this device's open files */
|
fusd_file_t **files; /* Array of this device's open files */
|
||||||
int array_size; /* Size of the array pointed to by 'files' */
|
int array_size; /* Size of the array pointed to by 'files' */
|
||||||
|
|||||||
262
kfusd/kfusd.c
262
kfusd/kfusd.c
@@ -37,8 +37,9 @@
|
|||||||
* Jeremy Elson <jelson@circlemud.org>
|
* Jeremy Elson <jelson@circlemud.org>
|
||||||
* Copyright (c) 2001, Sensoria Corporation
|
* Copyright (c) 2001, Sensoria Corporation
|
||||||
* Copyright (c) 2002-2003, Regents of the University of California
|
* Copyright (c) 2002-2003, Regents of the University of California
|
||||||
|
* Copyright (c) 2007 Monty and Xiph.Org
|
||||||
*
|
*
|
||||||
* $Id: kfusd.c,v 1.97 2003/07/11 22:29:39 cerpa Exp $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -90,7 +91,7 @@
|
|||||||
/* Default debug level for FUSD messages. Has no effect unless
|
/* Default debug level for FUSD messages. Has no effect unless
|
||||||
* CONFIG_FUSD_DEBUG is defined. */
|
* CONFIG_FUSD_DEBUG is defined. */
|
||||||
#ifndef CONFIG_FUSD_DEBUGLEVEL
|
#ifndef CONFIG_FUSD_DEBUGLEVEL
|
||||||
#define CONFIG_FUSD_DEBUGLEVEL 2
|
#define CONFIG_FUSD_DEBUGLEVEL 3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Define this to check for memory leaks */
|
/* Define this to check for memory leaks */
|
||||||
@@ -103,11 +104,6 @@
|
|||||||
* __wake_up. */
|
* __wake_up. */
|
||||||
/* #define CONFIG_FUSD_USE_WAKEUPSYNC */
|
/* #define CONFIG_FUSD_USE_WAKEUPSYNC */
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,9)
|
|
||||||
# define vsnprintf(str, size, format, ap) vsprintf(str, format, ap)
|
|
||||||
# define snprintf(str, len, args...) sprintf(str, args)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
|
||||||
|
|
||||||
#define CLASS class_simple
|
#define CLASS class_simple
|
||||||
@@ -132,14 +128,25 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline struct kobject * to_kobj(struct dentry * dentry)
|
||||||
|
{
|
||||||
|
struct sysfs_dirent * sd = dentry->d_fsdata;
|
||||||
|
if(sd)
|
||||||
|
return ((struct kobject *) sd->s_element);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define to_class(obj) container_of(obj, struct class, subsys.kset.kobj)
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
#include "fusd.h"
|
#include "fusd.h"
|
||||||
#include "fusd_msg.h"
|
#include "fusd_msg.h"
|
||||||
#include "kfusd.h"
|
#include "kfusd.h"
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
|
||||||
# error "***FUSD doesn't work before Linux Kernel v2.4.0"
|
# error "***FUSD doesn't work before Linux Kernel v2.6.13"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
STATIC struct cdev* fusd_control_device;
|
STATIC struct cdev* fusd_control_device;
|
||||||
@@ -181,6 +188,10 @@ STATIC int fusd_debug_level = CONFIG_FUSD_DEBUGLEVEL;
|
|||||||
module_param(fusd_debug_level, int, S_IRUGO);
|
module_param(fusd_debug_level, int, S_IRUGO);
|
||||||
|
|
||||||
#define BUFSIZE 1000 /* kernel's kmalloc pool has a 1012-sized bucket */
|
#define BUFSIZE 1000 /* kernel's kmalloc pool has a 1012-sized bucket */
|
||||||
|
static int debug_throttle = 0; /* emit a maximum number of debug
|
||||||
|
messages, else it's possible to take
|
||||||
|
out the machine accidentally if a
|
||||||
|
daemon disappears with open files */
|
||||||
|
|
||||||
STATIC void rdebug_real(char *fmt, ...)
|
STATIC void rdebug_real(char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -188,6 +199,9 @@ STATIC void rdebug_real(char *fmt, ...)
|
|||||||
int len;
|
int len;
|
||||||
char *message;
|
char *message;
|
||||||
|
|
||||||
|
if(debug_throttle > 100) return;
|
||||||
|
debug_throttle++;
|
||||||
|
|
||||||
/* I'm kmallocing since you don't really want 1k on the stack. I've
|
/* I'm kmallocing since you don't really want 1k on the stack. I've
|
||||||
* had stack overflow problems before; the kernel stack is quite
|
* had stack overflow problems before; the kernel stack is quite
|
||||||
* small... */
|
* small... */
|
||||||
@@ -634,8 +648,8 @@ STATIC struct fusd_transaction* fusd_find_incomplete_transaction(fusd_file_t *fu
|
|||||||
|
|
||||||
if (transaction->subcmd != subcmd)
|
if (transaction->subcmd != subcmd)
|
||||||
{
|
{
|
||||||
RDEBUG(2, "Incomplete transaction %ld thrown out, was expecting subcmd %d but received %d",
|
RDEBUG(2, "Incomplete transaction %ld thrown out, was expecting subcmd %d but received %d",
|
||||||
transaction->transid, transaction->subcmd, subcmd);
|
transaction->transid, transaction->subcmd, subcmd);
|
||||||
fusd_cleanup_transaction(fusd_file, transaction);
|
fusd_cleanup_transaction(fusd_file, transaction);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1164,7 +1178,7 @@ STATIC int fusd_client_release(struct inode *inode, struct file *file)
|
|||||||
if (retval >= 0)
|
if (retval >= 0)
|
||||||
retval = fusd_fops_call_wait(fusd_file, NULL, transaction);
|
retval = fusd_fops_call_wait(fusd_file, NULL, transaction);
|
||||||
|
|
||||||
RDEBUG(5, "fusd_client_release: call_wait %d", retval);
|
RDEBUG(5, "fusd_client_release: call_wait %d", retval);
|
||||||
/* delete the file off the device's file-list, and free it. note
|
/* delete the file off the device's file-list, and free it. note
|
||||||
* that device may be a zombie right now and may be freed when we
|
* that device may be a zombie right now and may be freed when we
|
||||||
* come back from free_fusd_file. we only release the lock if the
|
* come back from free_fusd_file. we only release the lock if the
|
||||||
@@ -1195,6 +1209,10 @@ STATIC ssize_t fusd_client_read(struct file *file , char *buf,
|
|||||||
int retval = -EPIPE;
|
int retval = -EPIPE;
|
||||||
|
|
||||||
GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
|
GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
|
||||||
|
|
||||||
|
if(ZOMBIE(fusd_dev))
|
||||||
|
goto zombie_dev;
|
||||||
|
|
||||||
LOCK_FUSD_FILE(fusd_file);
|
LOCK_FUSD_FILE(fusd_file);
|
||||||
|
|
||||||
RDEBUG(3, "got a read on /dev/%s (owned by pid %d) from pid %d",
|
RDEBUG(3, "got a read on /dev/%s (owned by pid %d) from pid %d",
|
||||||
@@ -1203,7 +1221,7 @@ STATIC ssize_t fusd_client_read(struct file *file , char *buf,
|
|||||||
transaction = fusd_find_incomplete_transaction(fusd_file, FUSD_READ);
|
transaction = fusd_find_incomplete_transaction(fusd_file, FUSD_READ);
|
||||||
if (transaction && transaction->size > count)
|
if (transaction && transaction->size > count)
|
||||||
{
|
{
|
||||||
RDEBUG(3, "Incomplete I/O transaction %ld thrown out, as the transaction's size of %d bytes was greater than "
|
RDEBUG(2, "Incomplete I/O transaction %ld thrown out, as the transaction's size of %d bytes was greater than "
|
||||||
"the retry's size of %d bytes", transaction->transid, transaction->size, (int)count);
|
"the retry's size of %d bytes", transaction->transid, transaction->size, (int)count);
|
||||||
|
|
||||||
fusd_cleanup_transaction(fusd_file, transaction);
|
fusd_cleanup_transaction(fusd_file, transaction);
|
||||||
@@ -1273,6 +1291,7 @@ STATIC ssize_t fusd_client_read(struct file *file , char *buf,
|
|||||||
|
|
||||||
invalid_file:
|
invalid_file:
|
||||||
invalid_dev:
|
invalid_dev:
|
||||||
|
zombie_dev:
|
||||||
RDEBUG(3, "got a read on client file from pid %d, driver has disappeared",
|
RDEBUG(3, "got a read on client file from pid %d, driver has disappeared",
|
||||||
current->pid);
|
current->pid);
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
@@ -1362,13 +1381,17 @@ STATIC ssize_t fusd_client_write(struct file *file,
|
|||||||
struct fusd_transaction* transaction;
|
struct fusd_transaction* transaction;
|
||||||
|
|
||||||
GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
|
GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
|
||||||
|
|
||||||
|
if(ZOMBIE(fusd_dev))
|
||||||
|
goto zombie_dev;
|
||||||
|
|
||||||
LOCK_FUSD_FILE(fusd_file);
|
LOCK_FUSD_FILE(fusd_file);
|
||||||
|
|
||||||
RDEBUG(3, "got a write on /dev/%s (owned by pid %d) from pid %d",
|
RDEBUG(3, "got a write on /dev/%s (owned by pid %d) from pid %d",
|
||||||
NAME(fusd_dev), fusd_dev->pid, current->pid);
|
NAME(fusd_dev), fusd_dev->pid, current->pid);
|
||||||
|
|
||||||
transaction = fusd_find_incomplete_transaction(fusd_file, FUSD_WRITE);
|
transaction = fusd_find_incomplete_transaction(fusd_file, FUSD_WRITE);
|
||||||
if (transaction && transaction->size == length)
|
if (transaction && transaction->size != length)
|
||||||
{
|
{
|
||||||
RDEBUG(2, "Incomplete I/O transaction %ld thrown out, as the transaction's size of %d bytes was not equal to "
|
RDEBUG(2, "Incomplete I/O transaction %ld thrown out, as the transaction's size of %d bytes was not equal to "
|
||||||
"the retry's size of %d bytes", transaction->transid, transaction->size, (int) length);
|
"the retry's size of %d bytes", transaction->transid, transaction->size, (int) length);
|
||||||
@@ -1437,7 +1460,8 @@ STATIC ssize_t fusd_client_write(struct file *file,
|
|||||||
|
|
||||||
invalid_file:
|
invalid_file:
|
||||||
invalid_dev:
|
invalid_dev:
|
||||||
RDEBUG(3, "got a read on client file from pid %d, driver has disappeared",
|
zombie_dev:
|
||||||
|
RDEBUG(3, "got a write on client file from pid %d, driver has disappeared",
|
||||||
current->pid);
|
current->pid);
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
}
|
}
|
||||||
@@ -1453,6 +1477,10 @@ STATIC int fusd_client_ioctl(struct inode *inode, struct file *file,
|
|||||||
struct fusd_transaction* transaction;
|
struct fusd_transaction* transaction;
|
||||||
|
|
||||||
GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
|
GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
|
||||||
|
|
||||||
|
if(ZOMBIE(fusd_dev))
|
||||||
|
goto zombie_dev;
|
||||||
|
|
||||||
LOCK_FUSD_FILE(fusd_file);
|
LOCK_FUSD_FILE(fusd_file);
|
||||||
|
|
||||||
RDEBUG(3, "got an ioctl on /dev/%s (owned by pid %d) from pid %d",
|
RDEBUG(3, "got an ioctl on /dev/%s (owned by pid %d) from pid %d",
|
||||||
@@ -1527,7 +1555,8 @@ STATIC int fusd_client_ioctl(struct inode *inode, struct file *file,
|
|||||||
|
|
||||||
invalid_file:
|
invalid_file:
|
||||||
invalid_dev:
|
invalid_dev:
|
||||||
RDEBUG(3, "got a read on client file from pid %d, driver has disappeared",
|
zombie_dev:
|
||||||
|
RDEBUG(3, "got an ioctl on client file from pid %d, driver has disappeared",
|
||||||
current->pid);
|
current->pid);
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
}
|
}
|
||||||
@@ -1576,6 +1605,10 @@ static int fusd_client_mmap(struct file *file, struct vm_area_struct * vma)
|
|||||||
struct fusd_mmap_instance* mmap_instance;
|
struct fusd_mmap_instance* mmap_instance;
|
||||||
|
|
||||||
GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
|
GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
|
||||||
|
|
||||||
|
if(ZOMBIE(fusd_dev))
|
||||||
|
goto zombie_dev;
|
||||||
|
|
||||||
LOCK_FUSD_FILE(fusd_file);
|
LOCK_FUSD_FILE(fusd_file);
|
||||||
|
|
||||||
RDEBUG(3, "got a mmap on /dev/%s (owned by pid %d) from pid %d",
|
RDEBUG(3, "got a mmap on /dev/%s (owned by pid %d) from pid %d",
|
||||||
@@ -1626,6 +1659,7 @@ static int fusd_client_mmap(struct file *file, struct vm_area_struct * vma)
|
|||||||
|
|
||||||
invalid_file:
|
invalid_file:
|
||||||
invalid_dev:
|
invalid_dev:
|
||||||
|
zombie_dev:
|
||||||
RDEBUG(3, "got a mmap on client file from pid %d, driver has disappeared",
|
RDEBUG(3, "got a mmap on client file from pid %d, driver has disappeared",
|
||||||
current->pid);
|
current->pid);
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
@@ -1886,6 +1920,11 @@ STATIC int fusd_polldiff_reply(fusd_dev_t *fusd_dev, fusd_msg_t *msg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC int systest (struct super_block *sb,void *data){
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
STATIC int fusd_register_device(fusd_dev_t *fusd_dev,
|
STATIC int fusd_register_device(fusd_dev_t *fusd_dev,
|
||||||
register_msg_t register_msg)
|
register_msg_t register_msg)
|
||||||
{
|
{
|
||||||
@@ -1899,10 +1938,6 @@ STATIC int fusd_register_device(fusd_dev_t *fusd_dev,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* user can only register one device per instance */
|
|
||||||
// if (fusd_dev->handle != 0)
|
|
||||||
// return -EBUSY;
|
|
||||||
|
|
||||||
register_msg.name[FUSD_MAX_NAME_LENGTH] = '\0';
|
register_msg.name[FUSD_MAX_NAME_LENGTH] = '\0';
|
||||||
|
|
||||||
/* make sure that there isn't already a device by this name */
|
/* make sure that there isn't already a device by this name */
|
||||||
@@ -1936,7 +1971,7 @@ STATIC int fusd_register_device(fusd_dev_t *fusd_dev,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(fusd_dev->class_name, register_msg.clazz);
|
strcpy(fusd_dev->class_name, register_msg.clazz);
|
||||||
|
|
||||||
/* allocate memory for the class name, and copy */
|
/* allocate memory for the class name, and copy */
|
||||||
if ((fusd_dev->dev_name = KMALLOC(strlen(register_msg.devname)+1, GFP_KERNEL)) == NULL) {
|
if ((fusd_dev->dev_name = KMALLOC(strlen(register_msg.devname)+1, GFP_KERNEL)) == NULL) {
|
||||||
@@ -1944,71 +1979,131 @@ STATIC int fusd_register_device(fusd_dev_t *fusd_dev,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(fusd_dev->dev_name, register_msg.devname);
|
strcpy(fusd_dev->dev_name, register_msg.devname);
|
||||||
|
|
||||||
dev_id = 0;
|
dev_id = 0;
|
||||||
|
|
||||||
if((error = alloc_chrdev_region(&dev_id, 0, 1, fusd_dev->name)) < 0)
|
if((error = alloc_chrdev_region(&dev_id, 0, 1, fusd_dev->name)) < 0)
|
||||||
{
|
{
|
||||||
printk(KERN_ERR "alloc_chrdev_region failed status: %d\n", error);
|
printk(KERN_ERR "alloc_chrdev_region failed status: %d\n", error);
|
||||||
goto register_failed;
|
goto register_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
fusd_dev->dev_id = dev_id;
|
||||||
|
|
||||||
|
fusd_dev->handle = cdev_alloc();
|
||||||
|
if(fusd_dev->handle == NULL)
|
||||||
|
{
|
||||||
|
printk(KERN_ERR "cdev_alloc() failed\n");
|
||||||
|
error = -ENOMEM;
|
||||||
|
goto register_failed3;
|
||||||
|
}
|
||||||
|
|
||||||
|
fusd_dev->handle->owner = THIS_MODULE;
|
||||||
|
fusd_dev->handle->ops = &fusd_client_fops;
|
||||||
|
|
||||||
|
kobject_set_name(&fusd_dev->handle->kobj, fusd_dev->name);
|
||||||
|
|
||||||
|
if((error = cdev_add(fusd_dev->handle, dev_id, 1)) < 0)
|
||||||
|
{
|
||||||
|
printk(KERN_ERR "cdev_add failed status: %d\n", error);
|
||||||
|
kobject_put(&fusd_dev->handle->kobj);
|
||||||
|
goto register_failed3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look up class in sysfs */
|
||||||
|
|
||||||
|
{
|
||||||
|
struct CLASS *sys_class = NULL;
|
||||||
|
struct file_system_type *sysfs = get_fs_type("sysfs");
|
||||||
|
struct dentry *classdir = NULL;
|
||||||
|
struct dentry *classdir2 = NULL;
|
||||||
|
struct super_block *sb = NULL;
|
||||||
|
|
||||||
|
if(sysfs){
|
||||||
|
sb = sget (sysfs, systest, NULL,NULL);
|
||||||
|
|
||||||
|
/* because put_filesystem isn't exported */
|
||||||
|
module_put(sysfs->owner);
|
||||||
|
|
||||||
|
if(sb){
|
||||||
|
struct dentry *root = sb->s_root;
|
||||||
|
|
||||||
|
if(root){
|
||||||
|
struct qstr name;
|
||||||
|
|
||||||
|
name.name = "class";
|
||||||
|
name.len = 5;
|
||||||
|
name.hash = full_name_hash(name.name, name.len);
|
||||||
|
classdir = d_lookup(root, &name);
|
||||||
|
|
||||||
|
if(classdir){
|
||||||
|
name.name = register_msg.clazz;
|
||||||
|
name.len = strlen(name.name);
|
||||||
|
name.hash = full_name_hash(name.name, name.len);
|
||||||
|
classdir2 = d_lookup(classdir, &name);
|
||||||
|
|
||||||
|
if(classdir2){
|
||||||
|
// jackpot. extract the class.
|
||||||
|
struct kobject *ko = to_kobj(classdir2);
|
||||||
|
sys_class = (ko?to_class(ko):NULL);
|
||||||
|
|
||||||
|
if(!sys_class)
|
||||||
|
RDEBUG(2, "WARNING: sysfs entry for %s has no kobject!\n",register_msg.clazz);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
RDEBUG(2, "WARNING: sysfs does not list a class directory!\n");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
RDEBUG(2, "WARNING: unable to access root firectory in sysfs!\n");
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
RDEBUG(2, "WARNING: unable to access superblock for sysfs!\n");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
RDEBUG(2, "WARNING: sysfs not mounted or unavailable!\n");
|
||||||
|
}
|
||||||
|
|
||||||
fusd_dev->dev_id = dev_id;
|
if(sys_class){
|
||||||
|
RDEBUG(3, "Found entry for class '%s' in sysfs\n",register_msg.clazz);
|
||||||
fusd_dev->handle = cdev_alloc();
|
fusd_dev->clazz = sys_class;
|
||||||
if(fusd_dev->handle == NULL)
|
fusd_dev->owns_class = 0;
|
||||||
|
}else{
|
||||||
|
RDEBUG(3, "Sysfs has no entry for '%s'; registering new class\n",register_msg.clazz);
|
||||||
|
fusd_dev->clazz = class_create(THIS_MODULE, fusd_dev->class_name);
|
||||||
|
if(IS_ERR(fusd_dev->clazz))
|
||||||
{
|
{
|
||||||
printk(KERN_ERR "cdev_alloc() failed\n");
|
error = PTR_ERR(fusd_dev->clazz);
|
||||||
error = -ENOMEM;
|
printk(KERN_ERR "class_create failed status: %d\n", error);
|
||||||
goto register_failed3;
|
goto register_failed4;
|
||||||
}
|
}
|
||||||
|
fusd_dev->owns_class = 1;
|
||||||
|
}
|
||||||
|
|
||||||
fusd_dev->handle->owner = THIS_MODULE;
|
if(classdir)
|
||||||
fusd_dev->handle->ops = &fusd_client_fops;
|
dput(classdir);
|
||||||
|
if(classdir2)
|
||||||
|
dput(classdir2);
|
||||||
|
|
||||||
kobject_set_name(&fusd_dev->handle->kobj, fusd_dev->name);
|
if(sb){
|
||||||
|
up_write(&sb->s_umount);
|
||||||
|
deactivate_super(sb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((error = cdev_add(fusd_dev->handle, dev_id, 1)) < 0)
|
fusd_dev->class_device = CLASS_DEVICE_CREATE(fusd_dev->clazz, NULL, fusd_dev->dev_id, NULL, fusd_dev->dev_name);
|
||||||
{
|
if(fusd_dev->class_device == NULL)
|
||||||
printk(KERN_ERR "cdev_add failed status: %d\n", error);
|
{
|
||||||
kobject_put(&fusd_dev->handle->kobj);
|
error = PTR_ERR(fusd_dev->class_device);
|
||||||
goto register_failed3;
|
printk(KERN_ERR "class_device_create failed status: %d\n", error);
|
||||||
}
|
goto register_failed5;
|
||||||
|
}
|
||||||
|
|
||||||
// Hack to add my class to the sound class
|
/* make sure the registration was successful */
|
||||||
if(strcmp("sound", register_msg.clazz) == 0)
|
|
||||||
{
|
|
||||||
fusd_dev->clazz = sound_class;
|
|
||||||
fusd_dev->owns_class = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fusd_dev->clazz = class_create(THIS_MODULE, fusd_dev->class_name);
|
|
||||||
if(IS_ERR(fusd_dev->clazz))
|
|
||||||
{
|
|
||||||
error = PTR_ERR(fusd_dev->clazz);
|
|
||||||
printk(KERN_ERR "class_create failed status: %d\n", error);
|
|
||||||
goto register_failed4;
|
|
||||||
}
|
|
||||||
fusd_dev->owns_class = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fusd_dev->class_device = CLASS_DEVICE_CREATE(fusd_dev->clazz, NULL, fusd_dev->dev_id, NULL, fusd_dev->dev_name);
|
|
||||||
if(fusd_dev->class_device == NULL)
|
|
||||||
{
|
|
||||||
error = PTR_ERR(fusd_dev->class_device);
|
|
||||||
printk(KERN_ERR "class_device_create failed status: %d\n", error);
|
|
||||||
goto register_failed5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure the registration was successful */
|
|
||||||
/*
|
|
||||||
if (fusd_dev->handle == 0) {
|
if (fusd_dev->handle == 0) {
|
||||||
error = -EIO;
|
error = -EIO;
|
||||||
goto register_failed;
|
goto register_failed;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/* remember the user's private data so we can pass it back later */
|
/* remember the user's private data so we can pass it back later */
|
||||||
fusd_dev->private_data = register_msg.device_info;
|
fusd_dev->private_data = register_msg.device_info;
|
||||||
@@ -2111,16 +2206,15 @@ STATIC int fusd_release(struct inode *inode, struct file *file)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(fusd_dev->handle)
|
if(fusd_dev->handle){
|
||||||
{
|
class_device_destroy(fusd_dev->clazz, fusd_dev->dev_id);
|
||||||
class_device_destroy(fusd_dev->clazz, fusd_dev->dev_id);
|
if(fusd_dev->owns_class)
|
||||||
if(fusd_dev->owns_class)
|
{
|
||||||
{
|
class_destroy(fusd_dev->clazz);
|
||||||
class_destroy(fusd_dev->clazz);
|
}
|
||||||
}
|
cdev_del(fusd_dev->handle);
|
||||||
cdev_del(fusd_dev->handle);
|
unregister_chrdev_region(fusd_dev->dev_id, 1);
|
||||||
unregister_chrdev_region(fusd_dev->dev_id, 1);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* mark the driver as being gone */
|
/* mark the driver as being gone */
|
||||||
zombify_dev(fusd_dev);
|
zombify_dev(fusd_dev);
|
||||||
@@ -2654,7 +2748,7 @@ STATIC void fusd_status_build_text(fusd_statcontext_t *fs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
len += snprintf(buf + len, buf_size - len,
|
len += snprintf(buf + len, buf_size - len,
|
||||||
"\nFUSD $Revision: 1.97-kor-hacked-11 $ - %d devices used by %d clients\n",
|
"\nFUSD $Revision$ - %d devices used by %d clients\n",
|
||||||
total_files, total_clients);
|
total_files, total_clients);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -2803,7 +2897,7 @@ STATIC int init_fusd(void)
|
|||||||
|
|
||||||
|
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"fusd: starting, $Revision: 1.97-kor-hacked-11 $, $Date: 2003/07/11 22:29:39 $");
|
"fusd: starting, $Revision$, $Date$");
|
||||||
#ifdef CVSTAG
|
#ifdef CVSTAG
|
||||||
printk(", release %s", CVSTAG);
|
printk(", release %s", CVSTAG);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -35,10 +35,10 @@
|
|||||||
*
|
*
|
||||||
* authors: jelson and girod
|
* authors: jelson and girod
|
||||||
*
|
*
|
||||||
* $Id: libfusd.c,v 1.61 2003/07/11 22:29:39 cerpa Exp $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char libfusd_c_id[] = "$Id: libfusd.c,v 1.61 2003/07/11 22:29:39 cerpa Exp $";
|
char libfusd_c_id[] = "$Id$";
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
149
make.include
149
make.include
@@ -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)
|
|
||||||
Reference in New Issue
Block a user