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
This commit is contained in:
Glenn L McGrath 2003-11-30 23:46:06 +00:00
parent 5be6a200f0
commit 3860b2ebd6
3 changed files with 197 additions and 238 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
#ifdef CONFIG_DEVFSD_VERBOSE
msg_logger( NO_DIE, LOG_INFO, "read config file: %s\n", path);
#endif
return;
errno=0;
}
msg_logger(( (optional == 0) && (errno == ENOENT) )? DIE : NO_DIE, LOG_ERR, " %s: %m\n", path);
read_config_file_err:
#ifdef CONFIG_DEVFSD_VERBOSE
msg_logger(((optional == 0 ) && (errno == ENOENT))? DIE : NO_DIE, LOG_ERR, "read config file: %s: %m\n", path);
#endif
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;
dest_stat.st_mode = 0;
snprintf (dpath, sizeof dpath, "%s%s", mount_point, spath + rootlen);
lstat (dpath, &dest_stat);
while ( (de = readdir (dp) ) != NULL )
{
char spath[STRING_LENGTH], dpath[STRING_LENGTH];
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);
struct stat source_stat, dest_stat;
dest_stat.st_mode = 0;
if ( S_ISDIR (source_stat.st_mode) )
dir_operation(RESTORE, spath, rootlen,NULL);
}
if ( (strcmp (de->d_name, ".") == 0) || (strcmp (de->d_name, "..") == 0) )
continue;
snprintf (spath, sizeof spath, "%s/%s", dir_name, de->d_name);
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_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