Patch from Tito, size optimisation, cleanup noise when in debugging mode, adds support for MODLOAD keyword in devfsd.conf, provides a cleaned up version of example/devfsd.conf
No binary (build failed)
—
(log yok)
| @@ -25,11 +25,10 @@ UNREGISTER .* RMNEWCOMPAT | |
| # Enable module autoloading. You may comment this out if you don't use | |
| # autoloading | |
| - | # Not supported by busybox |
| - | #LOOKUP .* MODLOAD |
| - | # Maybe one of these works for busybox |
| - | #LOOKUP .* EXECUTE /sbin/modprobe -k -v -C /etc/modules.devfs * |
| - | #REGISTER .* EXECUTE /sbin/modprobe -k -v -C /etc/modules.devfs * |
| + | # Supported by busybox when CONFIG_DEVFSD_MODLOAD is set. |
| + | # This actually doesn't work with busybox modutils but needs |
| + | # the real modutils' modprobe |
| + | LOOKUP .* MODLOAD |
| # Uncomment the following if you want to set the group to "tty" for the | |
| # pseudo-tty devices. This is necessary so that mesg(1) can later be used to | |
| @@ -68,7 +67,6 @@ RESTORE /lib/dev-state | |
| REGISTER ^cdroms/cdrom0$ EXECUTE /bin/ln -sf $devname cdrom | |
| UNREGISTER ^cdroms/cdrom0$ EXECUTE /bin/rm -f cdrom | |
| - | |
| #REGISTER ^v4l/video0$ CFUNCTION GLOBAL mksymlink v4l/video0 video | |
| #UNREGISTER ^v4l/video0$ CFUNCTION GLOBAL unlink video | |
| #REGISTER ^radio0$ CFUNCTION GLOBAL mksymlink radio0 radio | |
| @@ -80,18 +78,23 @@ REGISTER ^radio0$ EXECUTE /bin/ln -sf radio0 radio | |
| UNREGISTER ^radio0$ EXECUTE /bin/rm -f radio | |
| # ALSA stuff | |
| - | # Not supported by busybox |
| #LOOKUP snd MODLOAD ACTION snd | |
| - | # Maybe this works for busybox |
| - | #LOOKUP snd EXECUTE /sbin/modprobe -k -v -C /etc/modules.devfs snd |
| # Uncomment this to let PAM manage devfs | |
| + | # Not supported by busybox |
| #REGISTER .* CFUNCTION /lib/security/pam_console_apply_devfsd.so pam_console_apply_single $devpath | |
| # Uncomment this to manage USB mouse | |
| + | # Not supported by busybox |
| #REGISTER ^input/mouse0$ CFUNCTION GLOBAL mksymlink $devname usbmouse | |
| #UNREGISTER ^input/mouse0$ CFUNCTION GLOBAL unlink usbmouse | |
| # Busybox | |
| + | #REGISTER ^input/mouse0$ EXECUTE /bin/ln -sf $devname usbmouse |
| + | #UNREGISTER ^input/mouse0$ EXECUTE /bin/rm -f usbmouse |
| + | # Not supported by busybox |
| + | #REGISTER ^input/mice$ CFUNCTION GLOBAL mksymlink $devname usbmouse |
| + | #UNREGISTER ^input/mice$ CFUNCTION GLOBAL unlink usbmouse |
| + | # Busybox |
| REGISTER ^input/mice$ EXECUTE /bin/ln -sf $devname usbmouse | |
| UNREGISTER ^input/mice$ EXECUTE /bin/rm -f usbmouse | |
| @@ -107,75 +110,24 @@ LOOKUP ^(ide/hd/c[0-9]+b[0-9]+t[0-9]+u[0-9]+)p[0-9]+$ EXECUTE /bin/dd if=$mntpn | |
| LOOKUP ^(hd[a-z])[0-9]+$ EXECUTE /bin/dd if=$mntpnt/\1 of=/dev/null count=1 | |
| # IDE-SCSI NEWCOMPAT /dev/sd/* names | |
| #LOOKUP ^(sd/c[0-9]+b[0-9]+t[0-9]+u[0-9]+)p[0-9]+$ EXECUTE /bin/dd if=$mntpnt/\1 of=/dev/null count=1 | |
| - | # SCSI OLDCOMPAT /dev/scd? names |
| + | #SCSI OLDCOMPAT /dev/scd? names |
| LOOKUP ^(scd+)[0-9]+$ EXECUTE /bin/dd if=$mntpnt/\1 of=/dev/null count=1 | |
| REGISTER ^dvb/card[0-9]+/[^/]+$ PERMISSIONS root.video 0660 | |
| - | # Busybox |
| + | # Not supported by busybox |
| #REGISTER ^dvb/card([0-9]+)/([^/0-9]*)[0-9]+$ CFUNCTION GLOBAL mksymlink /dev/$devname ost/\2\1 | |
| #UNREGISTER ^dvb/card([0-9]+)/([^/0-9]*)[0-9]+$ CFUNCTION GLOBAL unlink ost/\2\1 | |
| + | # Busybox |
| REGISTER ^dvb/card([0-9]+)/([^/0-9]*)[0-9]+$ EXECUTE /bin/ln -sf /dev/$devname ost/\2\1 | |
| UNREGISTER ^dvb/card([0-9]+)/([^/0-9]*)[0-9]+$ EXECUTE /bin/rm -f ost/\2\1 | |
| # Include package-generated files from /etc/devfs/conf.d | |
| # Supported by busybox | |
| - | #OPTIONAL_INCLUDE /etc/devfs/conf.d/dvd.conf |
| - | #INCLUDE /etc/devfs/conf.d/dvd.conf |
| - | #OPTIONAL_INCLUDE /etc/devfs/conf.d/ |
| - | #INCLUDE /etc/devfs/conf.d/ |
| - | |
| - | #/etc/devfs/conf.d/dvd.conf |
| - | #REGISTER ^ide/host0/bus1/target1/lun0/cd$ CFUNCTION GLOBAL mksymlink ide/host0/bus1/target1/lun0/cd dvd |
| - | #UNREGISTER ^ide/host0/bus1/target1/lun0/cd$ CFUNCTION GLOBAL unlink dvd |
| - | REGISTER ^ide/host0/bus1/target1/lun0/cd$ EXECUTE ln -sf ide/host0/bus1/target1/lun0/cd dvd |
| - | UNREGISTER ^ide/host0/bus1/target1/lun0/cd$ EXECUTE rm -f dvd |
| - | |
| - | #/etc/devfs/conf.d/dynamic.conf |
| - | # dynamic desktop and co |
| - | |
| - | REGISTER .*/part.* EXECUTE /etc/dynamic/scripts/part.script add $devpath |
| - | UNREGISTER .*/part.* EXECUTE /etc/dynamic/scripts/part.script del $devpath |
| - | |
| - | REGISTER v4l/video.* EXECUTE /etc/dynamic/scripts/webcam.script add $devpath |
| - | UNREGISTER v4l/video.* EXECUTE /etc/dynamic/scripts/webcam.script del $devpath |
| - | |
| - | REGISTER usb/scanner.* EXECUTE /etc/dynamic/scripts/scanner.script add $devpath |
| - | UNREGISTER usb/scanner.* EXECUTE /etc/dynamic/scripts/scanner.script del $devpath |
| - | |
| - | REGISTER usb/rio500 EXECUTE /etc/dynamic/scripts/rio500.script add $devpath |
| - | UNREGISTER usb/rio500 EXECUTE /etc/dynamic/scripts/rio500.script del $devpath |
| - | |
| - | REGISTER usb/tts/[13579] EXECUTE /etc/dynamic/scripts/visor.script add $devpath |
| - | UNREGISTER usb/tts/[13579] EXECUTE /etc/dynamic/scripts/visor.script del $devpath |
| - | |
| - | REGISTER (usb/lp.*|printers/.*) EXECUTE /etc/dynamic/scripts/lp.script add $devpath |
| - | UNREGISTER (usb/lp.*|printers/.*) EXECUTE /etc/dynamic/scripts/lp.script del $devpath |
| - | |
| - | #/etc/devfs/conf.d/modem.conf |
| - | #REGISTER ^$ CFUNCTION GLOBAL mksymlink modem |
| - | #UNREGISTER ^$ CFUNCTION GLOBAL unlink modem |
| - | REGISTER ^tts/0$ EXECUTE ln -sf $devname modem |
| - | UNREGISTER ^$ EXECUTE rm -f modem |
| - | |
| - | #/etc/devfs/conf.d/mouse.conf |
| - | #REGISTER ^misc/psaux$ CFUNCTION GLOBAL mksymlink misc/psaux mouse |
| - | #UNREGISTER ^misc/psaux$ CFUNCTION GLOBAL unlink mouse |
| - | REGISTER ^misc/psaux$ EXECUTE ln -sf misc/psaux mouse |
| - | UNREGISTER ^misc/psaux$ EXECUTE rm -f mouse |
| - | |
| - | #/etc/devfs/conf.d/psaux.conf |
| - | #REGISTER ^misc/psaux$ CFUNCTION GLOBAL mksymlink misc/psaux psaux |
| - | #UNREGISTER ^misc/psaux$ CFUNCTION GLOBAL unlink psaux |
| - | REGISTER ^misc/psaux$ EXECUTE ln -sf misc/psaux psaux |
| - | UNREGISTER ^misc/psaux$ EXECUTE rm -f psaux |
| - | |
| - | #/etc/devfs/conf.d/rdvd.conf |
| - | REGISTER ^ide/host0/bus1/target1/lun0/cd$ EXECUTE /etc/dynamic/scripts/rawdevice.script add /dev/ide/host0/bus1/target1/lun0/cd /dev/rdvd |
| - | UNREGISTER ^ide/host0/bus1/target1/lun0/cd$ EXECUTE /etc/dynamic/scripts/rawdevice.script del /dev/rdvd |
| - | |
| - | #/etc/devfs/conf.d/ttyS0.conf |
| - | #REGISTER ^tts/0$ CFUNCTION GLOBAL mksymlink tts/0 ttyS0 |
| - | #UNREGISTER ^tts/0$ CFUNCTION GLOBAL unlink ttyS0 |
| - | REGISTER ^tts/0$ EXECUTE ln -sf $devname ttyS0 |
| - | UNREGISTER ^tts/0$ EXECUTE rm -f ttyS0 |
| + | # INCLUDE /etc/devfs/conf.d/ |
| + | INCLUDE /etc/devfs/busybox/ |
| + | # Busybox: just for testing |
| + | #INCLUDE /etc/devfs/nothing/ |
| + | #INCLUDE /etc/devfs/nothing/nothing |
| + | #OPTIONAL_INCLUDE /etc/devfs/nothing/ |
| + | #OPTIONAL_INCLUDE /etc/devfs/nothing/nothing |
| @@ -47,6 +47,13 @@ config CONFIG_DEVFSD | |
| Provides compatibility with old device names on a devfs systems. | |
| You should set it to true if you have devfs enabled. | |
| + | config CONFIG_DEVFSD_MODLOAD |
| + | bool "Adds support for MODLOAD action" |
| + | default n |
| + | depends on CONFIG_DEVFSD |
| + | help |
| + | This actually doesn't work with busybox modutils but needs the real modutils. |
| + | |
| config CONFIG_DEVFSD_VERBOSE | |
| bool "Increases logging to stderr and syslog" | |
| default n | |
| @@ -129,6 +129,8 @@ struct devfsd_notify_struct | |
| #define BUFFER_SIZE 16384 | |
| #define DEVFSD_VERSION "1.3.25" | |
| #define CONFIG_FILE "/etc/devfsd.conf" | |
| + | #define MODPROBE "/sbin/modprobe" |
| + | #define CONFIG_MODULES_DEVFS "/etc/modules.devfs" |
| #define MAX_ARGS (6 + 1) | |
| #define MAX_SUBEXPR 10 | |
| #define STRING_LENGTH 255 | |
| @@ -138,10 +140,15 @@ struct devfsd_notify_struct | |
| #define GID 1 | |
| /* for msg_logger(), do_ioctl(), | |
| - | fork_and_execute() and xopendir(). */ |
| - | # define DIE 1 |
| + | fork_and_execute() */ |
| + | # define DIE 1 |
| # define NO_DIE 0 | |
| + | /* for dir_operation() */ |
| + | #define RESTORE 0 |
| + | #define SERVICE 1 |
| + | #define READ_CONFIG 2 |
| + | |
| /* Update only after changing code to reflect new protocol */ | |
| #define DEVFSD_PROTOCOL_REVISION_DAEMON 5 | |
| @@ -151,11 +158,11 @@ struct devfsd_notify_struct | |
| #endif | |
| #define AC_PERMISSIONS 0 | |
| - | #define AC_MODLOAD 1 /* not supported by busybox */ |
| + | #define AC_MODLOAD 1 |
| #define AC_EXECUTE 2 | |
| #define AC_MFUNCTION 3 /* not supported by busybox */ | |
| #define AC_CFUNCTION 4 /* not supported by busybox */ | |
| - | #define AC_COPY 5 |
| + | #define AC_COPY 5 |
| #define AC_IGNORE 6 | |
| #define AC_MKOLDCOMPAT 7 | |
| #define AC_MKNEWCOMPAT 8 | |
| @@ -209,6 +216,8 @@ struct get_variable_info | |
| char devpath[STRING_LENGTH]; | |
| }; | |
| + | static void dir_operation(int , const char * , int, unsigned long* ); |
| + | static void service(struct stat statbuf, char *path); |
| static int st_expr_expand(char *, unsigned, const char *, const char *(*) (const char *, void *), void *); | |
| static const char *get_old_name(const char *, unsigned, char *, unsigned, unsigned); | |
| static int mksymlink (const char *oldpath, const char *newpath); | |
| @@ -219,16 +228,18 @@ static void service_name (const struct devfsd_notify_struct *); | |
| static void action_permissions (const struct devfsd_notify_struct *, const struct config_entry_struct *); | |
| static void action_execute (const struct devfsd_notify_struct *, const struct config_entry_struct *, | |
| const regmatch_t *, unsigned); | |
| + | #ifdef CONFIG_DEVFSD_MODLOAD |
| + | static void action_modload (const struct devfsd_notify_struct *info, const struct config_entry_struct *entry); |
| + | #endif |
| static void action_copy (const struct devfsd_notify_struct *, const struct config_entry_struct *, | |
| const regmatch_t *, unsigned); | |
| static void action_compat (const struct devfsd_notify_struct *, unsigned); | |
| static void free_config (void); | |
| - | static void do_restore (const char *, int); |
| + | static void restore(char *spath, struct stat source_stat, int rootlen); |
| static int copy_inode (const char *, const struct stat *, mode_t, const char *, const struct stat *); | |
| static mode_t get_mode (const char *); | |
| static void signal_handler (int); | |
| static const char *get_variable (const char *, void *); | |
| - | static void do_scan_and_service (const char *); |
| static int make_dir_tree (const char *); | |
| static int expand_expression(char *, unsigned, const char *, const char *(*)(const char *, void *), void *, | |
| const char *, const regmatch_t *, unsigned ); | |
| @@ -243,7 +254,6 @@ static char *write_old_sd_name (char *, unsigned, unsigned, char *); | |
| static void msg_logger(int die, int pri, const char * fmt, ... ); | |
| static void do_ioctl(int die, int fd, int request, unsigned long event_mask_flag); | |
| static void fork_and_execute(int die, char *arg0, char **arg ); | |
| - | DIR * xopendir(int die, const char * dir_name); |
| static int get_uid_gid ( int, const char *); | |
| static void safe_memcpy( char * dest, const char * src, int len); | |
| @@ -318,7 +328,7 @@ static void msg_logger(int die, int pri, const char * fmt, ... ) | |
| static void do_ioctl(int die, int fd, int request, unsigned long event_mask_flag) | |
| { | |
| if (ioctl (fd, request, event_mask_flag) != 0) | |
| - | msg_logger(die, LOG_ERR, "ioctl() failed: %m\n"); |
| + | msg_logger(die, LOG_ERR, "ioctl(): %m\n"); |
| } | |
| static void fork_and_execute(int die, char *arg0, char **arg ) | |
| @@ -345,21 +355,10 @@ static void fork_and_execute(int die, char *arg0, char **arg ) | |
| if(arg0 != NULL ) | |
| { | |
| execvp (arg0, arg); | |
| - | msg_logger(DIE, LOG_ERR, "execvp() failed: %s: %m\n", arg0); |
| + | msg_logger(DIE, LOG_ERR, "execvp(): %s: %m\n", arg0); |
| } | |
| } | |
| - | |
| - | DIR * xopendir(int die, const char * dir_name) |
| - | { |
| - | DIR *dp; |
| - | |
| - | if ( ( dp = opendir (dir_name) ) == NULL ) |
| - | msg_logger( die, LOG_ERR, "opendir() failed: %s: %m\n", dir_name); |
| - | /* if die == DIE not reached else return NULL */ |
| - | return dp; |
| - | } |
| - | |
| static void safe_memcpy( char *dest, const char *src, int len) | |
| { | |
| memcpy (dest , src , len ); | |
| @@ -437,7 +436,7 @@ int devfsd_main (int argc, char **argv) | |
| umask (0); | |
| read_config_file (CONFIG_FILE, FALSE, &event_mask); | |
| /* Do the scan before forking, so that boot scripts see the finished product */ | |
| - | do_scan_and_service (mount_point); |
| + | dir_operation(SERVICE,mount_point,0,NULL); |
| if (no_polling) | |
| exit (0); | |
| if (do_daemon) | |
| @@ -457,7 +456,7 @@ int devfsd_main (int argc, char **argv) | |
| free_config (); | |
| read_config_file (CONFIG_FILE, FALSE, &event_mask); | |
| if (do_scan) | |
| - | do_scan_and_service (mount_point); |
| + | dir_operation(SERVICE,mount_point,0,NULL); |
| } | |
| } /* End Function main */ | |
| @@ -476,32 +475,17 @@ static void read_config_file (const char *path, int optional, unsigned long *eve | |
| struct stat statbuf; | |
| FILE *fp; | |
| char buf[STRING_LENGTH]; | |
| + | char *line=NULL; |
| #ifdef CONFIG_DEVFSD_DEBUG | |
| msg_logger( NO_DIE, LOG_INFO, "read_config_file()\n"); | |
| #endif | |
| - | |
| if (stat (path, &statbuf) != 0 || statbuf.st_size == 0 ) | |
| - | msg_logger((optional == 0 )? DIE : NO_DIE, LOG_ERR, " %s: %m\n", path); |
| + | goto read_config_file_err; |
| if ( S_ISDIR (statbuf.st_mode) ) | |
| { | |
| - | |
| - | DIR *dp; |
| - | struct dirent *de; |
| - | |
| - | dp = xopendir(DIE, path); |
| - | |
| - | while ( ( de = readdir (dp) ) != NULL ) |
| - | { |
| - | char fname[STRING_LENGTH]; |
| - | |
| - | if (de->d_name[0] == '.') |
| - | continue; |
| - | snprintf (fname, STRING_LENGTH, "%s/%s", path, de->d_name); |
| - | read_config_file (fname, optional, event_mask); |
| - | } |
| - | closedir (dp); |
| + | dir_operation(READ_CONFIG, path, 0, event_mask); |
| return; | |
| } | |
| @@ -509,9 +493,13 @@ static void read_config_file (const char *path, int optional, unsigned long *eve | |
| { | |
| while (fgets (buf, STRING_LENGTH, fp) != NULL) | |
| { | |
| - | char *line; |
| - | |
| - | buf[strlen (buf) - 1] = '\0'; |
| + | /* GETS(3) Linux Programmer's Manual |
| + | fgets() reads in at most one less than size characters from stream and |
| + | stores them into the buffer pointed to by s. Reading stops after an |
| + | EOF or a newline. If a newline is read, it is stored into the buffer. |
| + | A '\0' is stored after the last character in the buffer. |
| + | */ |
| + | /*buf[strlen (buf) - 1] = '\0';*/ |
| /* Skip whitespace */ | |
| for (line = buf; isspace (*line); ++line) | |
| /*VOID*/; | |
| @@ -520,12 +508,13 @@ static void read_config_file (const char *path, int optional, unsigned long *eve | |
| process_config_line (line, event_mask); | |
| } | |
| fclose (fp); | |
| + | errno=0; |
| + | } |
| + | read_config_file_err: |
| #ifdef CONFIG_DEVFSD_VERBOSE | |
| - | msg_logger( NO_DIE, LOG_INFO, "read config file: %s\n", path); |
| + | msg_logger(((optional == 0 ) && (errno == ENOENT))? DIE : NO_DIE, LOG_ERR, "read config file: %s: %m\n", path); |
| #endif | |
| - | return; |
| - | } |
| - | msg_logger(( (optional == 0) && (errno == ENOENT) )? DIE : NO_DIE, LOG_ERR, " %s: %m\n", path); |
| + | return; |
| } /* End Function read_config_file */ | |
| static void process_config_line (const char *line, unsigned long *event_mask) | |
| @@ -541,6 +530,8 @@ static void process_config_line (const char *line, unsigned long *event_mask) | |
| char when[STRING_LENGTH], what[STRING_LENGTH]; | |
| char name[STRING_LENGTH]; | |
| char * msg=""; | |
| + | char *ptr; |
| + | |
| #ifdef CONFIG_DEVFSD_DEBUG | |
| msg_logger( NO_DIE, LOG_INFO, "process_config_line()\n"); | |
| #endif | |
| @@ -562,12 +553,15 @@ static void process_config_line (const char *line, unsigned long *event_mask) | |
| (strcasecmp (when, "OPTIONAL_INCLUDE") == 0) ) | |
| { | |
| st_expr_expand (name, STRING_LENGTH, name, get_variable, NULL ); | |
| + | #ifdef CONFIG_DEVFSD_VERBOSE |
| + | msg_logger( NO_DIE, LOG_INFO, "%sinclude: %s\n",(toupper (when[0]) == 'I') ? "": "optional_", name); |
| + | #endif |
| read_config_file (name, (toupper (when[0]) == 'I') ? FALSE : TRUE, event_mask); | |
| return; | |
| } | |
| if (strcasecmp (when, "RESTORE") == 0) | |
| { | |
| - | do_restore ( name, strlen (name) ); |
| + | dir_operation(RESTORE,name, strlen (name),NULL); |
| return; | |
| } | |
| if (num_args < 3) | |
| @@ -591,8 +585,6 @@ static void process_config_line (const char *line, unsigned long *event_mask) | |
| if (strcasecmp (what, "PERMISSIONS") == 0) | |
| { | |
| - | char *ptr; |
| - | |
| new->action.what = AC_PERMISSIONS; | |
| /* Get user and group */ | |
| if ( ( ptr = strchr (p[0], '.') ) == NULL ) | |
| @@ -607,6 +599,14 @@ static void process_config_line (const char *line, unsigned long *event_mask) | |
| /* Get mode */ | |
| new->u.permissions.mode = get_mode (p[1]); | |
| } | |
| + | #ifdef CONFIG_DEVFSD_MODLOAD |
| + | else if (strcasecmp (what, "MODLOAD") == 0) |
| + | /*This action will pass "/dev/$devname" (i.e. "/dev/" prefixed to |
| + | the device name) to the module loading facility. In addition, |
| + | the /etc/modules.devfs configuration file is used.*/ |
| + | |
| + | new->action.what = AC_MODLOAD; |
| + | #endif |
| else if (strcasecmp (what, "EXECUTE") == 0) | |
| { | |
| new->action.what = AC_EXECUTE; | |
| @@ -673,11 +673,6 @@ static int do_servicing (int fd, unsigned long event_mask) | |
| #endif | |
| /* Tell devfs what events we care about */ | |
| tmp_event_mask = event_mask; | |
| - | /* May need to trap inode creates to watch for syslogd(8) starting */ |
| - | /*if (!syslog_is_open && !no_syslog) |
| - | { |
| - | tmp_event_mask |= 1 << DEVFSD_NOTIFY_CREATE; *//*FIXME I'm not sure if this line is needed. TITO */ |
| - | /*}*/ |
| do_ioctl(DIE, fd, DEVFSDIOC_SET_EVENT_MASK, tmp_event_mask); | |
| while (!caught_signal) | |
| { | |
| @@ -689,14 +684,6 @@ static int do_servicing (int fd, unsigned long event_mask) | |
| continue; /* Yes, the order is important */ | |
| if (bytes < 1) | |
| break; | |
| - | /* Special trap for "/dev/log" creation */ |
| - | /* Open syslog, now that "/dev/log" exists */ |
| - | /*if (!syslog_is_open && !no_syslog && |
| - | (info.type == DEVFSD_NOTIFY_CREATE) &&(strcmp (info.devname, "log") == 0) ) |
| - | { |
| - | do_open_syslog (); |
| - | do_ioctl(DIE, fd, DEVFSDIOC_SET_EVENT_MASK, event_mask);*/ /*FIXME I'm not sure if this line is needed. TITO */ |
| - | /*}*/ |
| service_name (&info); | |
| } | |
| if (caught_signal) | |
| @@ -752,6 +739,14 @@ static void service_name (const struct devfsd_notify_struct *info) | |
| #endif | |
| action_permissions (info, entry); | |
| break; | |
| + | #ifdef CONFIG_DEVFSD_MODLOAD |
| + | case AC_MODLOAD: |
| + | #ifdef CONFIG_DEVFSD_DEBUG |
| + | msg_logger( NO_DIE, LOG_INFO, "AC_MODLOAD\n"); |
| + | #endif |
| + | action_modload (info, entry); |
| + | break; |
| + | #endif |
| case AC_EXECUTE: | |
| #ifdef CONFIG_DEVFSD_DEBUG | |
| msg_logger( NO_DIE, LOG_INFO, "AC_EXECUTE\n"); | |
| @@ -805,13 +800,39 @@ static void action_permissions (const struct devfsd_notify_struct *info, | |
| chown (info->devname, entry->u.permissions.uid, entry->u.permissions.gid) != 0) | |
| { | |
| #ifdef CONFIG_DEVFSD_VERBOSE | |
| - | msg_logger( NO_DIE, LOG_ERR, "chmod() or chown() error for: %s: %m\n",info->devname); |
| + | msg_logger( NO_DIE, LOG_ERR, "chmod() or chown(): %s: %m\n",info->devname); |
| #endif | |
| return; | |
| } | |
| } /* End Function action_permissions */ | |
| + | #ifdef CONFIG_DEVFSD_MODLOAD |
| + | static void action_modload (const struct devfsd_notify_struct *info, |
| + | const struct config_entry_struct *entry) |
| + | /* [SUMMARY] Load a module. |
| + | <info> The devfs change. |
| + | <entry> The config file entry. |
| + | [RETURNS] Nothing. |
| + | */ |
| + | { |
| + | char *argv[6]; |
| + | char device[STRING_LENGTH]; |
| + | |
| + | argv[0] = MODPROBE; |
| + | argv[1] = "-k"; |
| + | argv[2] = "-C"; |
| + | argv[3] = CONFIG_MODULES_DEVFS; |
| + | argv[4] = device; |
| + | argv[5] = NULL; |
| + | #ifdef CONFIG_DEVFSD_DEBUG |
| + | msg_logger( NO_DIE, LOG_INFO, "action_modload()\n"); |
| + | #endif |
| + | snprintf (device, sizeof (device), "/dev/%s", info->devname); |
| + | fork_and_execute(DIE, argv[0], argv); |
| + | } /* End Function action_modload */ |
| + | #endif |
| + | |
| static void action_execute (const struct devfsd_notify_struct *info, | |
| const struct config_entry_struct *entry, | |
| const regmatch_t *regexpr, unsigned int numexpr) | |
| @@ -903,8 +924,7 @@ static void action_copy (const struct devfsd_notify_struct *info, | |
| regexpr, numexpr); | |
| if ( !make_dir_tree (destination) || lstat (source, &source_stat) != 0) | |
| - | goto action_copy_error; |
| - | |
| + | return; |
| lstat (destination, &dest_stat); | |
| new_mode = source_stat.st_mode & ~S_ISVTX; | |
| if (info->type == DEVFSD_NOTIFY_CREATE) | |
| @@ -913,13 +933,11 @@ static void action_copy (const struct devfsd_notify_struct *info, | |
| new_mode |= S_ISVTX; | |
| #ifdef CONFIG_DEVFSD_VERBOSE | |
| if ( !copy_inode (destination, &dest_stat, new_mode, source, &source_stat) ) | |
| - | action_copy_error: |
| - | msg_logger( NO_DIE, LOG_ERR, "error copying: %s to %s: %m\n", source, destination); |
| + | msg_logger( NO_DIE, LOG_ERR, "copy_inode(): %s to %s: %m\n", source, destination); |
| #else | |
| - | copy_inode (destination, &dest_stat, new_mode, source,&source_stat); |
| - | action_copy_error: |
| - | return; |
| + | copy_inode (destination, &dest_stat, new_mode, source, &source_stat); |
| #endif | |
| + | return; |
| } /* End Function action_copy */ | |
| static void action_compat (const struct devfsd_notify_struct *info, | |
| @@ -1041,53 +1059,26 @@ static void action_compat (const struct devfsd_notify_struct *info, | |
| } | |
| } /* End Function action_compat */ | |
| - | static void do_restore (const char *dir_name, int rootlen) |
| - | /* [SUMMARY] Restore state from a directory. |
| - | <dir_name> The directory containing the backing store. |
| - | <rootlen> The length of the root of the state directory hierarchy. |
| - | [RETURNS] Nothing. |
| - | */ |
| + | static void restore(char *spath, struct stat source_stat, int rootlen) |
| { | |
| - | DIR *dp; |
| - | struct dirent *de; |
| + | char dpath[STRING_LENGTH]; |
| + | struct stat dest_stat; |
| #ifdef CONFIG_DEVFSD_DEBUG | |
| - | msg_logger( NO_DIE, LOG_INFO, "do_restore()\n"); |
| + | msg_logger( NO_DIE, LOG_INFO, "restore()\n"); |
| #endif | |
| - | if( (dp = xopendir(NO_DIE, dir_name))== NULL) |
| - | return; |
| - | |
| - | while ( (de = readdir (dp) ) != NULL ) |
| - | { |
| - | char spath[STRING_LENGTH], dpath[STRING_LENGTH]; |
| - | |
| - | struct stat source_stat, dest_stat; |
| - | dest_stat.st_mode = 0; |
| - | |
| - | if ( (strcmp (de->d_name, ".") == 0) || (strcmp (de->d_name, "..") == 0) ) |
| - | continue; |
| - | |
| - | snprintf (spath, sizeof spath, "%s/%s", dir_name, de->d_name); |
| + | dest_stat.st_mode = 0; |
| + | snprintf (dpath, sizeof dpath, "%s%s", mount_point, spath + rootlen); |
| + | lstat (dpath, &dest_stat); |
| - | if (lstat (spath, &source_stat) != 0) |
| - | { |
| - | #ifdef CONFIG_DEVFSD_VERBOSE |
| - | msg_logger( NO_DIE, LOG_ERR, "%s: %m\n", spath); |
| - | #endif |
| - | continue; |
| - | } |
| - | snprintf (dpath, sizeof dpath, "%s%s", mount_point, spath + rootlen); |
| - | lstat (dpath, &dest_stat); |
| + | if ( S_ISLNK (source_stat.st_mode) || (source_stat.st_mode & S_ISVTX) ) |
| + | copy_inode (dpath, &dest_stat, (source_stat.st_mode & ~S_ISVTX) , spath, &source_stat); |
| - | if ( S_ISLNK (source_stat.st_mode) || (source_stat.st_mode & S_ISVTX) ) |
| - | copy_inode (dpath, &dest_stat, (source_stat.st_mode & ~S_ISVTX) , spath, &source_stat); |
| + | if ( S_ISDIR (source_stat.st_mode) ) |
| + | dir_operation(RESTORE, spath, rootlen,NULL); |
| + | } |
| - | if ( S_ISDIR (source_stat.st_mode) ) |
| - | do_restore (spath, rootlen); |
| - | } |
| - | closedir (dp); |
| - | } /* End Function do_restore */ |
| static int copy_inode (const char *destpath, const struct stat *dest_stat, | |
| mode_t new_mode, | |
| @@ -1148,9 +1139,7 @@ static int copy_inode (const char *destpath, const struct stat *dest_stat, | |
| close (fd); | |
| if (val != 0 || chmod (destpath, new_mode & ~S_IFMT) != 0) | |
| break; | |
| - | if (chown (destpath, source_stat->st_uid, source_stat->st_gid) == 0) |
| - | return (TRUE); |
| - | break; |
| + | goto do_chown; |
| case S_IFLNK: | |
| if ( ( val = readlink (sourcepath, symlink_val, STRING_LENGTH - 1) ) < 0 ) | |
| break; | |
| @@ -1164,23 +1153,19 @@ static int copy_inode (const char *destpath, const struct stat *dest_stat, | |
| close (fd); | |
| if (chmod (destpath, new_mode & ~S_IFMT) != 0) | |
| break; | |
| - | if (chown (destpath, source_stat->st_uid, source_stat->st_gid) == 0) |
| - | return (TRUE); |
| - | break; |
| + | goto do_chown; |
| case S_IFBLK: | |
| case S_IFCHR: | |
| case S_IFIFO: | |
| if (mknod (destpath, new_mode, source_stat->st_rdev) != 0) | |
| break; | |
| - | if (chown (destpath, source_stat->st_uid, source_stat->st_gid) == 0) |
| - | return (TRUE); |
| - | break; |
| + | goto do_chown; |
| case S_IFDIR: | |
| if (mkdir (destpath, new_mode & ~S_IFMT) != 0) | |
| break; | |
| + | do_chown: |
| if (chown (destpath, source_stat->st_uid, source_stat->st_gid) == 0) | |
| return (TRUE); | |
| - | return (TRUE); |
| /*break;*/ | |
| } | |
| return (FALSE); | |
| @@ -1228,15 +1213,14 @@ static int get_uid_gid (int flag, const char *string) | |
| { | |
| struct passwd *pw_ent; | |
| struct group *grp_ent; | |
| - | char * msg_a="user"; |
| - | char * msg_b="U"; |
| + | char * msg="user"; |
| #ifdef CONFIG_DEVFSD_DEBUG | |
| msg_logger( NO_DIE, LOG_INFO, "get_uid_gid()\n"); | |
| if(flag != UID && flag != GID ) | |
| - | msg_logger( DIE, LOG_ERR,"flag != UID && flag != GID\n"); |
| + | msg_logger( DIE, LOG_ERR,"get_uid_gid(): flag != UID && flag != GID\n"); |
| #endif | |
| if ( isdigit (string[0]) || ( (string[0] == '-') && isdigit (string[1]) ) ) | |
| @@ -1248,12 +1232,9 @@ static int get_uid_gid (int flag, const char *string) | |
| if ( flag == GID && ( grp_ent = getgrnam (string) ) != NULL ) | |
| return (grp_ent->gr_gid); | |
| else | |
| - | { |
| - | msg_a="group"; |
| - | msg_b="G"; |
| - | } |
| + | msg="group"; |
| - | msg_logger( NO_DIE, LOG_ERR,"unknown %s: %s, defaulting to %cID=0\n", msg_a, string, msg_b); |
| + | msg_logger( NO_DIE, LOG_ERR,"unknown %s: %s, defaulting to %cID=0\n", msg, string, msg[0] - 32); |
| return (0); | |
| }/* End Function get_uid_gid */ | |
| @@ -1264,7 +1245,7 @@ static mode_t get_mode (const char *string) | |
| */ | |
| { | |
| mode_t mode; | |
| - | |
| + | int i; |
| #ifdef CONFIG_DEVFSD_DEBUG | |
| msg_logger( NO_DIE, LOG_INFO, "get_mode()\n"); | |
| #endif | |
| @@ -1274,15 +1255,14 @@ static mode_t get_mode (const char *string) | |
| if (strlen (string) != 9) | |
| msg_logger( DIE, LOG_ERR, "bad mode: %s\n", string); | |
| mode = 0; | |
| - | if (string[0] == 'r') mode |= S_IRUSR; |
| - | if (string[1] == 'w') mode |= S_IWUSR; |
| - | if (string[2] == 'x') mode |= S_IXUSR; |
| - | if (string[3] == 'r') mode |= S_IRGRP; |
| - | if (string[4] == 'w') mode |= S_IWGRP; |
| - | if (string[5] == 'x') mode |= S_IXGRP; |
| - | if (string[6] == 'r') mode |= S_IROTH; |
| - | if (string[7] == 'w') mode |= S_IWOTH; |
| - | if (string[8] == 'x') mode |= S_IXOTH; |
| + | i= S_IRUSR; |
| + | while(i>0) |
| + | { |
| + | if(string[0]=='r'||string[0]=='w'||string[0]=='x') |
| + | mode+=i; |
| + | i=i/2; |
| + | string++; |
| + | } |
| return (mode); | |
| } /* End Function get_mode */ | |
| @@ -1341,10 +1321,34 @@ static const char *get_variable (const char *variable, void *info) | |
| return (NULL); | |
| } /* End Function get_variable */ | |
| - | static void do_scan_and_service (const char *dir_name) |
| + | static void service(struct stat statbuf, char *path) |
| + | { |
| + | struct devfsd_notify_struct info; |
| + | |
| + | #ifdef CONFIG_DEVFSD_DEBUG |
| + | msg_logger( NO_DIE, LOG_INFO, "service()\n"); |
| + | #endif |
| + | |
| + | memset (&info, 0, sizeof info); |
| + | info.type = DEVFSD_NOTIFY_REGISTERED; |
| + | info.mode = statbuf.st_mode; |
| + | info.major = major (statbuf.st_rdev); |
| + | info.minor = minor (statbuf.st_rdev); |
| + | info.uid = statbuf.st_uid; |
| + | info.gid = statbuf.st_gid; |
| + | snprintf (info.devname, sizeof (info.devname), "%s", path + strlen (mount_point) + 1); |
| + | info.namelen = strlen (info.devname); |
| + | service_name (&info); |
| + | if ( S_ISDIR (statbuf.st_mode) ) |
| + | dir_operation(SERVICE,path,0,NULL); |
| + | } |
| + | |
| + | static void dir_operation(int type, const char * dir_name, int var, unsigned long *event_mask) |
| /* [SUMMARY] Scan a directory tree and generate register events on leaf nodes. | |
| - | <dp> The directory pointer. This is closed upon completion. |
| + | <flag> To choose which function to perform |
| + | <dp> The directory pointer. This is closed upon completion. |
| <dir_name> The name of the directory. | |
| + | <rootlen> string length parameter. |
| [RETURNS] Nothing. | |
| */ | |
| { | |
| @@ -1353,20 +1357,24 @@ static void do_scan_and_service (const char *dir_name) | |
| struct dirent *de; | |
| char path[STRING_LENGTH]; | |
| + | |
| #ifdef CONFIG_DEVFSD_DEBUG | |
| - | msg_logger( NO_DIE, LOG_INFO, "do_scan_and_service ()\n"); |
| + | msg_logger( NO_DIE, LOG_INFO, "dir_operation()\n"); |
| #endif | |
| - | if((dp = xopendir(NO_DIE, dir_name))==NULL) |
| + | if((dp = opendir( dir_name))==NULL) |
| + | { |
| + | msg_logger( NO_DIE, LOG_ERR, "opendir(): %s: %m\n", dir_name); |
| return; | |
| + | } |
| while ( (de = readdir (dp) ) != NULL ) | |
| { | |
| - | struct devfsd_notify_struct info; |
| - | if ( (strcmp (de->d_name, ".") == 0) || (strcmp (de->d_name, "..") == 0) ) |
| + | if ( (strcmp (de->d_name, ".") == 0) || (strcmp (de->d_name, "..") == 0) ) |
| continue; | |
| - | snprintf (path, sizeof (path), "%s/%s", dir_name, de->d_name); |
| + | snprintf (path, sizeof (path), "%s%s%s", dir_name,(last_char_is(dir_name,'/')==NULL)?"/":"", de->d_name); |
| + | |
| if (lstat (path, &statbuf) != 0) | |
| { | |
| #ifdef CONFIG_DEVFSD_VERBOSE | |
| @@ -1374,18 +1382,18 @@ static void do_scan_and_service (const char *dir_name) | |
| #endif | |
| continue; | |
| } | |
| - | memset (&info, 0, sizeof info); |
| - | info.type = DEVFSD_NOTIFY_REGISTERED; |
| - | info.mode = statbuf.st_mode; |
| - | info.major = major (statbuf.st_rdev); |
| - | info.minor = minor (statbuf.st_rdev); |
| - | info.uid = statbuf.st_uid; |
| - | info.gid = statbuf.st_gid; |
| - | snprintf (info.devname, sizeof (info.devname), "%s", path + strlen (mount_point) + 1); |
| - | info.namelen = strlen (info.devname); |
| - | service_name (&info); |
| - | if ( S_ISDIR (statbuf.st_mode) ) |
| - | do_scan_and_service (path); |
| + | switch(type) |
| + | { |
| + | case SERVICE: |
| + | service(statbuf,path); |
| + | break; |
| + | case RESTORE: |
| + | restore(path, statbuf, var); |
| + | break; |
| + | case READ_CONFIG: |
| + | read_config_file (path, var, event_mask); |
| + | break; |
| + | } |
| } | |
| closedir (dp); | |
| } /* End Function do_scan_and_service */ | |
| @@ -1408,17 +1416,10 @@ static int mksymlink (const char *oldpath, const char *newpath) | |
| if (symlink (oldpath, newpath) != 0) | |
| { | |
| #ifdef CONFIG_DEVFSD_VERBOSE | |
| - | if (errno == EEXIST) |
| - | msg_logger( NO_DIE, LOG_INFO, "symlink(): %s: already exists\n", newpath); |
| - | else |
| - | { |
| - | msg_logger( NO_DIE, LOG_ERR, "symlink(): %s: %m\n", newpath); |
| - | return (-1); |
| - | } |
| - | #else |
| + | msg_logger( NO_DIE, LOG_ERR, "symlink(): %s to %s: %m\n", oldpath, newpath); |
| + | #endif |
| if (errno != EEXIST) | |
| return (-1); | |
| - | #endif |
| } | |
| return (0); | |
| } /* End Function mksymlink */ | |
| @@ -1701,7 +1702,6 @@ static char get_old_ide_name (unsigned int major, unsigned int minor) | |
| char c='a'; /* 97 */ | |
| int i=IDE0_MAJOR; | |
| - | |
| #ifdef CONFIG_DEVFSD_DEBUG | |
| msg_logger( NO_DIE, LOG_INFO, "get_old_ide_name()\n"); | |
| #endif | |