From 20a1f10d184ff39f42c8b10bd708687c13d304db Mon Sep 17 00:00:00 2001 From: ppisa Date: Tue, 16 Mar 2004 16:14:52 +0000 Subject: [PATCH] Cleaned-up PROC handling and checked on 2.4, 2.4-RT, 2.6 and compilation for 2.2 kernels. --- lincan/src/Makefile.std | 8 +- lincan/src/proc.c | 209 +++++++++++++++++++++------------------- 2 files changed, 116 insertions(+), 101 deletions(-) diff --git a/lincan/src/Makefile.std b/lincan/src/Makefile.std index f740504..40dacc3 100644 --- a/lincan/src/Makefile.std +++ b/lincan/src/Makefile.std @@ -122,6 +122,12 @@ ifdef PROC_FS O_OBJS += proc.o endif +ifdef SUBDIRS +EXTRA_CFLAGS += -I $(SUBDIRS) +else +EXTRA_CFLAGS += -I . +endif + # Target object file if any # this must be undefined for 2.5.xx kernels ifndef KERNEL_MODULE_V26 @@ -145,7 +151,7 @@ L_OBJS = # Kernel only objects with exported symbols (-DEXPORT_SYMTAB) LX_OBJS = # Additional CFLAGS -EXTRA_CFLAGS += -I . +EXTRA_CFLAGS += # Linux 2.4.2 and newer build system needs next can-objs = $(O_OBJS) diff --git a/lincan/src/proc.c b/lincan/src/proc.c index 254aabc..02522b1 100644 --- a/lincan/src/proc.c +++ b/lincan/src/proc.c @@ -19,16 +19,16 @@ int add_channel_to_procdir(struct candevice_t *candev); int remove_channel_from_procdir(void); int add_object_to_procdir(int chip_nr); -int remove_object_from_procdir(void); +int remove_object_from_procdir(int chip_nr); #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0)) -static int candev_readlink(struct proc_dir_entry *de, char *page); +static int can_proc_readlink(struct proc_dir_entry *ent, char *page); #endif static int cc=0; /* static counter for each CAN chip */ -struct canproc_t can_proc_base; -struct canproc_t *base=&can_proc_base; +static struct canproc_t can_proc_base; +static struct canproc_t *base=&can_proc_base; /* The following functions are needed only for kernel version 2.2. Kernel * version 2.4 already defines them for us. @@ -42,23 +42,36 @@ static void can_fill_inode(struct inode *inode, int fill) MOD_DEC_USE_COUNT; } -static struct proc_dir_entry * new_can_proc_entry(unsigned short inode, - const char *name, mode_t mode, nlink_t nlink, struct proc_dir_entry *parent) +static struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mode, + struct proc_dir_entry *parent) { struct proc_dir_entry *new_entry = NULL; + char *namestore; + int namelen; + + if(!name || !parent) + return NULL; + namelen=strlen(name); + if(!namelen) + return NULL; new_entry = (struct proc_dir_entry *) - can_checked_malloc(sizeof(struct proc_dir_entry)); + can_checked_malloc(sizeof(struct proc_dir_entry)+namelen+1); + if (new_entry == NULL) return NULL; memset(new_entry, 0, sizeof(struct proc_dir_entry)); - new_entry->low_ino = inode; - new_entry->namelen = strlen(name); - new_entry->name = name; + /* Store copy of the proc entry name */ + namestore = ((char *) new_entry) + sizeof(struct proc_dir_entry); + memcpy(namestore, name, namelen + 1); + + new_entry->low_ino = 0; + new_entry->namelen = namelen; + new_entry->name = namestore; new_entry->mode = mode; - new_entry->nlink = nlink; + new_entry->nlink = 0; new_entry->fill_inode = can_fill_inode; new_entry->parent = parent; @@ -67,7 +80,7 @@ static struct proc_dir_entry * new_can_proc_entry(unsigned short inode, return new_entry; } -int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent) +static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent) { if (del != NULL) { proc_unregister(parent, del->low_ino); @@ -76,7 +89,58 @@ int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *par } else return -ENODEV; } -#endif // Functions required for kernel 2.2 + + +static int can_proc_readlink(struct proc_dir_entry *ent, char *page) +{ + char *link_dest = (char*)ent->data; + + strcpy(page, link_dest); + return strlen(link_dest); +} + + + +/* This compatibility version of proc_symlink does not store local copy of destination */ +static inline struct proc_dir_entry *can_proc_symlink(const char *name, + struct proc_dir_entry *parent, const char *dest) +{ + struct proc_dir_entry *entry; + + + entry = can_create_proc_entry(name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, parent); + if (entry == NULL) + return NULL; + entry->readlink_proc = can_proc_readlink; + entry->data = dest; + return entry; +} + +#else /* Functions forwarded for kernel 2.4 and above */ + +static inline struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mode, + struct proc_dir_entry *parent) +{ + return create_proc_entry(name, mode, parent); +} + + +/* This does not fully follow linux 2.4 and 2.6 prototype to simplify 2.2.x compatibility */ +/* The newer kernels use entry name instead of pointer to the entry */ +static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent) +{ + if(!del) return -ENODEV; + remove_proc_entry(del->name,parent); + return 0; +} + +static inline struct proc_dir_entry *can_proc_symlink(const char *name, + struct proc_dir_entry *parent, const char *dest) +{ + return proc_symlink(name, parent, dest); +} + +#endif /* Functions required for kernel 2.2 */ /* can_init_procdir registers the entire CAN directory tree recursively at * the proc system. @@ -85,13 +149,8 @@ int can_init_procdir(void) { int board; struct candevice_t *candev; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0)) - base->can_proc_entry = new_can_proc_entry(0, "can", S_IFDIR | S_IRUGO | - S_IXUGO, 0, &proc_root); -#else - base->can_proc_entry = create_proc_entry("can", S_IFDIR | S_IRUGO | + base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO | S_IXUGO, &proc_root); -#endif if (base->can_proc_entry == NULL) return -ENODEV; @@ -108,12 +167,9 @@ int can_delete_procdir(void) { if (remove_channel_from_procdir()) return -ENODEV; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0)) + /* name: "can" */ if (can_remove_proc_entry(base->can_proc_entry, &proc_root)) return -ENODEV; -#else - remove_proc_entry("can", &proc_root); -#endif return 0; } @@ -131,17 +187,11 @@ int add_channel_to_procdir(struct candevice_t *candev) sprintf(base->channel[cc]->ch_name, "channel%d",cc); -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0)) - base->channel[cc]->ch_entry = new_can_proc_entry(0, - base->channel[cc]->ch_name, - S_IFDIR | S_IRUGO | S_IXUGO, 0, - base->can_proc_entry); -#else - base->channel[cc]->ch_entry = create_proc_entry( + base->channel[cc]->ch_entry = can_create_proc_entry( base->channel[cc]->ch_name, S_IFDIR | S_IRUGO |S_IXUGO, base->can_proc_entry); -#endif + if (base->channel[cc]->ch_entry == NULL) return -ENODEV; @@ -158,16 +208,19 @@ int remove_channel_from_procdir(void) while (cc != 0) { cc--; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0)) + + if(!base->channel[cc]) continue; + + if (remove_object_from_procdir(cc)) + return -ENODEV; + + /* name: base->channel[cc]->ch_name */ if (can_remove_proc_entry(base->channel[cc]->ch_entry, base->can_proc_entry)) return -ENODEV; -#else - remove_proc_entry(base->channel[cc]->ch_name, - base->can_proc_entry); -#endif - if (remove_object_from_procdir()) - return -ENODEV; + + can_checked_free(base->channel[cc]); + base->channel[cc] = NULL; } return 0; @@ -190,94 +243,50 @@ int add_object_to_procdir(int chip_nr) sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i); sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev"); -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0)) - base->channel[chip_nr]->object[i]->obj_entry=new_can_proc_entry( - 0, base->channel[chip_nr]->object[i]->obj_name, - S_IFDIR | S_IRUGO | S_IXUGO, 0, - base->channel[chip_nr]->ch_entry); - if (base->channel[chip_nr]->object[i]->obj_entry == NULL) - return -ENODEV; - base->channel[chip_nr]->object[i]->lnk = new_can_proc_entry( - 0, base->channel[chip_nr]->object[i]->lnk_name, - S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, - 0, base->channel[chip_nr]->object[i]->obj_entry); - if (base->channel[chip_nr]->object[i]->lnk == NULL) - return -ENODEV; - sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can"); - base->channel[chip_nr]->object[i]->lnk->readlink_proc = - candev_readlink; - -#else - base->channel[chip_nr]->object[i]->obj_entry = create_proc_entry( + base->channel[chip_nr]->object[i]->obj_entry = can_create_proc_entry( base->channel[chip_nr]->object[i]->obj_name, S_IFDIR | S_IRUGO | S_IXUGO, base->channel[chip_nr]->ch_entry); if (base->channel[chip_nr]->object[i]->obj_entry == NULL) return -ENODEV; + sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can%d", chips_p[chip_nr]->msgobj[i]->minor); - base->channel[chip_nr]->object[i]->lnk = proc_symlink( + + base->channel[chip_nr]->object[i]->lnk = can_proc_symlink( base->channel[chip_nr]->object[i]->lnk_name, base->channel[chip_nr]->object[i]->obj_entry, base->channel[chip_nr]->object[i]->lnk_dev); if (base->channel[chip_nr]->object[i]->lnk == NULL) return -ENODEV; -#endif } return 0; } -int remove_object_from_procdir(void) +int remove_object_from_procdir(int chip_nr) { int i=0, obj=0; - obj=chips_p[cc]->max_objects; + obj=chips_p[chip_nr]->max_objects; for (i=0; ichannel[cc]->object[i]->lnk, - base->channel[cc]->object[i]->obj_entry)) + if(!base->channel[chip_nr]->object[i]) continue; + + /* name: base->channel[chip_nr]->object[i]->lnk_name */ + if (can_remove_proc_entry( base->channel[chip_nr]->object[i]->lnk, + base->channel[chip_nr]->object[i]->obj_entry)) return -ENODEV; + /* name: base->channel[chip_nr]->object[i]->obj_name */ if (can_remove_proc_entry( - base->channel[cc]->object[i]->obj_entry, - base->channel[cc]->ch_entry)) + base->channel[chip_nr]->object[i]->obj_entry, + base->channel[chip_nr]->ch_entry)) return -ENODEV; -#else - remove_proc_entry(base->channel[cc]->object[i]->lnk_name, - base->channel[cc]->object[i]->obj_entry); - remove_proc_entry(base->channel[cc]->object[i]->obj_name, - base->channel[cc]->ch_entry); -#endif - + + can_checked_free(base->channel[chip_nr]->object[i]); + + base->channel[chip_nr]->object[i]=NULL; } return 0; } -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0)) -static int candev_readlink(struct proc_dir_entry *de, char *page) -{ - int i=0, nchip=0, nobj=0; - char chip[20], object[20], tmp[6]; - - sprintf(chip, de->parent->parent->name+7); - sprintf(object, de->parent->name+6); - - for (i=0; imsgobj[nobj]->minor ); -} -#endif //End of candev_readlink for kernel 2.2 -- 2.39.2