⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devfsd.c

📁 devfsd 驱动对linux的补丁支持
💻 C
📖 第 1 页 / 共 5 页
字号:
			      unsigned long *event_mask);static void process_config_line (CONST char *line, unsigned long *event_mask);static void *dlsym_nofail (const char *file, void *handle, char *symbol);static int process_yp_line (int instatus, char *inkey, int inkeylen,			    char *inval, int invallen, char *indata);static void load_libnsl (void);static flag do_servicing (int fd, unsigned long event_mask);static void service_name (const struct devfsd_notify_struct *info);static void action_permissions (const struct devfsd_notify_struct *info,				const struct config_entry_struct *entry);static void action_modload (const struct devfsd_notify_struct *info,			    const struct config_entry_struct *entry);static void action_execute (const struct devfsd_notify_struct *info,			    const struct config_entry_struct *entry,			    const regmatch_t *regexpr, unsigned int numexpr);static void action_call_function (const struct devfsd_notify_struct *info,				  const struct config_entry_struct *entry,				  const regmatch_t *regexpr,				  unsigned int numexpr);static void action_copy (const struct devfsd_notify_struct *info,			 const struct config_entry_struct *entry,			 const regmatch_t *regexpr, unsigned int number);static void action_compat (const struct devfsd_notify_struct *info,			   unsigned int action);static void free_config ();static void do_restore (const char *dirname, int rootlen);static flag copy_inode (const char *destpath, const struct stat *deststat,			mode_t new_mode,			const char *sourcepath, const struct stat *sourcestat);static void do_debug (int fd);static uid_t get_uid (const char *string);static gid_t get_gid (const char *string);static mode_t get_mode (const char *string);static void signal_handler (int sig);static CONST char *get_variable (CONST char *variable, void *info);static void do_open_syslog ();static void do_scan_and_service (CONST char *dirname);static flag make_dir_tree (const char *path);static struct shared_object *get_shared_object (CONST char *name);static flag expand_expression(char *output, unsigned int outsize,			      const char *input,			      const char *(*get_variable)(const char *variable,                                                          void *info),                              void *info,                              const char *devname,                              const regmatch_t *ex, unsigned int numexp,                              FILE *errfp);static void expand_regexp (char *output, size_t outsize,			   const char *input, const char *devname,			   const regmatch_t *ex, unsigned int numex,			   FILE *errfp);/*  Private data  */static struct config_entry_struct *first_config = NULL;static struct config_entry_struct *last_config = NULL;static struct shared_object *first_so = NULL;static const char *mount_point = NULL;static flag no_syslog = FALSE;static char trace_level = 0;static flag debug_protocol = FALSE;static volatile flag caught_signal = FALSE;static volatile flag caught_sighup = FALSE;static struct initial_symlink_struct{    char *dest;    char *name;} initial_symlinks[] ={    {"/proc/self/fd", "fd"},    {"fd/0", "stdin"},    {"fd/1", "stdout"},    {"fd/2", "stderr"},    {NULL, NULL},};static int (*my_yp_all) (char *domain, char *map,			 struct ypall_callback *callback); /* = NULL */static int (*my_yp_get_default_domain) (char **domainptr); /* = NULL */static struct event_type{    unsigned int type;        /*  The DEVFSD_NOTIFY_* value                  */    CONST char *config_name;  /*  The name used in the config file           */    CONST char *debug_name;   /*  The name used when debugging the protocol  */} event_types[] ={    {DEVFSD_NOTIFY_REGISTERED,   "REGISTER",   "registered"},    {DEVFSD_NOTIFY_UNREGISTERED, "UNREGISTER", "unregistered"},    {DEVFSD_NOTIFY_ASYNC_OPEN,   "ASYNC_OPEN", "asynchronously opened"},    {DEVFSD_NOTIFY_CLOSE,        "CLOSE",      "closed"},    {DEVFSD_NOTIFY_LOOKUP,       "LOOKUP",     "lookup"},    {DEVFSD_NOTIFY_CHANGE,       "CHANGE",     "changed"},    {DEVFSD_NOTIFY_CREATE,       "CREATE",     "created"},    {DEVFSD_NOTIFY_DELETE,       "DELETE",     "deleted"},    {0xffffffff,                 NULL,         NULL}};/*  Public functions follow  */int main (int argc, char **argv){    flag print_version = FALSE;    flag debug_devfs = FALSE;    flag do_daemon = TRUE;    flag no_polling = FALSE;    int fd, proto_rev, count;    unsigned int devfs_debug_mask;    unsigned long event_mask = 0;    struct sigaction new_action;    struct stat statbuf;    static char usage[] = "devfsd mntpnt [-v] [-d] [-t num] [-D mask] [-fg] [-np]";    if (argc < 2)    {	fprintf (stderr, "Usage:\t%s\n", usage);	exit (1);    }    for (count = 2; count < argc; ++count)    {	if (strcmp (argv[count], "-v") == 0) print_version = TRUE;	else if (strcmp (argv[count], "-d") == 0)	{	    debug_protocol = TRUE;	    no_syslog = TRUE;	}	else if ( (strcmp (argv[count], "-t") == 0) && (count + 1 < argc) )	    trace_level = atoi (argv[++count]);	else if ( (strcmp (argv[count], "-D") == 0) && (++count < argc) )	{	    devfs_debug_mask = strtol (argv[count], NULL, 0);	    debug_devfs = TRUE;	}	else if (strcmp (argv[count], "-fg") == 0) do_daemon = FALSE;	else if (strcmp (argv[count], "-np") == 0) no_polling = TRUE;	else	{	    fprintf (stderr, "Usage:\t%s\n", usage);	    exit (1);	}    }    if (trace_level > 0) no_syslog = TRUE;    mount_point = argv[1];    if (chdir (mount_point) != 0)    {	fprintf (stderr, "Error changing directory to: \"%s\"\t%s\n",		 mount_point, ERRSTRING);	exit (1);    }    /*  Open dummy stdin, stdout and stderr if required, so that closing in	do_open_syslog() doesn't close other files  */    do fd = open ("/dev/null", O_RDWR, 0);    while ( (fd >= 0) && (fd < 3) );    close (fd);    if ( ( fd = open (".devfsd", O_RDONLY, 0) ) < 0 )    {	fprintf (stderr, "Error opening file: \".devfsd\"\t%s\n", ERRSTRING);	exit (1);    }    if (fcntl (fd, F_SETFD, FD_CLOEXEC) != 0)	fprintf (stderr, "Error setting close on exec for .devfsd\t%s\n",		 ERRSTRING);    if (ioctl (fd, DEVFSDIOC_GET_PROTO_REV, &proto_rev) != 0)    {	fprintf (stderr, "Error getting protocol revision\t%s\n", ERRSTRING);	exit (1);    }    if (!debug_devfs) setup_initial_entries ();    if (!print_version && !debug_protocol && !debug_devfs)    {	if (stat (CONFIG_FILE, &statbuf) != 0)	{	    fprintf (stderr, "device management daemon exiting as no %s\n",		     CONFIG_FILE);	    exit (0);	}	if (statbuf.st_size == 0)	{	    fprintf (stderr,		     "device management daemon exiting as %s is empty\n",		     CONFIG_FILE);	    exit (0);	}    }    if ( print_version || (trace_level > 1) || debug_protocol ||	 (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev) )    {	fprintf (stderr, "devfsd: Linux device filesystem daemon v%s\n",		 DEVFSD_VERSION);	fprintf (stderr,		 "(C) 1998-2001  Richard Gooch <rgooch@atnf.csiro.au>\n\n");	fprintf (stderr, "Daemon protocol revision:\t%d\n",		 DEVFSD_PROTOCOL_REVISION_DAEMON);	fprintf (stderr, "Kernel-side protocol revision:\t%d\n", proto_rev);	if (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev)	{	    fprintf (stderr, "Protocol mismatch!\n");	    exit (1);	}    }    if (print_version) exit (0);    if (debug_devfs)    {	if (ioctl (fd, DEVFSDIOC_SET_DEBUG_MASK, &devfs_debug_mask) != 0)	{	    fprintf (stderr, "Error setting debug mask\t%s\n", ERRSTRING);	    exit (1);	}	exit (0);    }    /*  Tell kernel we are special (i.e. we get to see hidden entries)  */    if (ioctl (fd, DEVFSDIOC_SET_EVENT_MASK, 0) != 0)    {	fprintf (stderr, "Error setting event mask\t%s\n", ERRSTRING);	exit (1);    }    if (debug_protocol) do_debug (fd);    sigemptyset (&new_action.sa_mask);    new_action.sa_flags = 0;    /*  Set up SIGHUP and SIGUSR1 handlers  */    new_action.sa_handler = signal_handler;    if (sigaction (SIGHUP, &new_action, NULL) != 0)    {	fprintf (stderr, "Error setting SIGHUP handler\t%s\n", ERRSTRING);	exit (1);    }    if (sigaction (SIGUSR1, &new_action, NULL) != 0)    {	fprintf (stderr, "Error setting SIGUSR1 handler\t%s\n", ERRSTRING);	exit (1);    }    if (trace_level < 1)    	fprintf (stderr, "Started device management daemon v%s for %s\n",		 DEVFSD_VERSION, mount_point);    else    	fprintf (stderr,		 "Started device management daemon v%s for %s at trace level %d\n",		 DEVFSD_VERSION, mount_point, trace_level);    /*  Set umask so that mknod(2), open(2) and mkdir(2) have complete control	over permissions  */    umask (0);    read_config (CONFIG_FILE, FALSE, &event_mask);    /*  Do the scan before forking, so that boot scripts see the finished	product  */    do_scan_and_service (mount_point);    if (no_polling) exit (0);    if (do_daemon)    {	/*  Release so that the child can grab it  */	if (ioctl (fd, DEVFSDIOC_RELEASE_EVENT_QUEUE, 0) != 0)	{	    fprintf (stderr, "Error releasing event queue\t%s\n", ERRSTRING);	    exit (1);	}	switch ( fork () )	{	  case 0:	    /*  Child  */	    break;	  case -1:	    /*  Error  */	    perror ("devfsd");	    exit (2);	    /*break;*/	  default:	    /*  Parent  */	    exit (0);	    /*break;*/	}	setsid ();        /*  Prevent hangups and become pgrp leader         */    }    else setpgid (0, 0);  /*  Become process group leader                    */    do_open_syslog ();    while (TRUE)    {	flag do_scan = do_servicing (fd, event_mask);	free_config ();	read_config (CONFIG_FILE, FALSE, &event_mask);	if (do_scan) do_scan_and_service (mount_point);    }}   /*  End Function main  *//*  Private functions follow  */static void setup_initial_entries (){    struct initial_symlink_struct *curr;    for (curr = initial_symlinks; curr->dest != NULL; ++curr)	symlink (curr->dest, curr->name);}   /*  End Function setup_initial_entries  */static void read_config (CONST char *location, flag optional,			 unsigned long *event_mask)/*  [SUMMARY] Read a configuration database.    <location> The location to read the database from. Either a filename or a    YP(NIS) map name prefixed with '+'.    <optional> If TRUE, the routine will silently ignore a missing config file.    <event_mask> The event mask is written here. This is not initialised.    [RETURNS] Nothing.*/{    if (location[0] == '+')    {	/*  It's a YP map  */	struct ypall_callback ypall_cbk;	char *domainname = NULL;	if (my_yp_all == NULL) load_libnsl ();	/*  If no domain: fail silently (probably too early)  */	if ( (*my_yp_get_default_domain) (&domainname) != 0 ) return;	if (domainname == NULL) return;	ypall_cbk.foreach = ( int (*) () ) process_yp_line;	ypall_cbk.data = (char *) event_mask;	if ( (*my_yp_all) (domainname, (char *) location + 1,&ypall_cbk) == 0 )	{	    if (syslog_is_open)		SYSLOG (LOG_INFO, "read map: \"%s\"\n", location + 1);	    return;	}	if (optional) return;	SYSLOG (LOG_ERR, "error reading map: \"%s\"\n", location + 1);	exit (1);    }    read_config_file (location, optional, event_mask);}   /*  End Function read_config   */static void read_config_file (CONST char *path, flag optional,			      unsigned long *event_mask)/*  [SUMMARY] Read a configuration database.    <path> The path to read the database from. If this is a directory, all    entries in that directory will be read (except hidden entries).    <optional> If TRUE, the routine will silently ignore a missing config file.    <event_mask> The event mask is written here. This is not initialised.    [RETURNS] Nothing.*/{    struct stat statbuf;    FILE *fp;    char buf[STRING_LENGTH];    if (stat (path, &statbuf) != 0)    {	if ( optional && (errno == ENOENT) ) return;	SYSLOG (LOG_ERR, "error opening file: \"%s\"\t%s\n",		path, ERRSTRING);	exit (1);    }    if ( S_ISDIR (statbuf.st_mode) )    {	DIR *dp;	struct dirent *de;	if ( ( dp = opendir (path) ) == NULL )	{	    SYSLOG (LOG_ERR, "error opening directory: \"%s\"\t%s\n",		    path, ERRSTRING);	    exit (1);	}	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);	return;    }    if ( ( fp = fopen (path, "r") ) == NULL )    {	if ( optional && (errno == ENOENT) ) return;	SYSLOG (LOG_ERR, "error opening file: \"%s\"\t%s\n", path, ERRSTRING);	exit (1);    }    if (trace_level > 2) fprintf (stderr, "Reading file: \"%s\"\n", path);    while (fgets (buf, STRING_LENGTH, fp) != NULL)    {	char *line;	buf[strlen (buf) - 1] = '\0';	/*  Skip whitespace  */	for (line = buf; isspace (*line); ++line);	if (line[0] == '\0') continue;	if (line[0] == '#') continue;	process_config_line (line, event_mask);    }    fclose (fp);    if (syslog_is_open)	SYSLOG (LOG_INFO, "read config file: \"%s\"\n", path);}   /*  End Function read_config_file   */static void process_config_line (CONST char *line, unsigned long *event_mask)/*  [SUMMARY] Process a line from a configuration file.    <line> The configuration line.    <event_mask> The event mask is written here. This is not initialised.    [RETURNS] Nothing.*/{    int err, num_args, count;    struct config_entry_struct *new;    char p[MAX_ARGS][STRING_LENGTH];    char when[STRING_LENGTH], what[STRING_LENGTH];    char name[STRING_LENGTH], tmp[STRING_LENGTH];    for (count = 0; count < MAX_ARGS; ++count) p[count][0] = '\0';    num_args = sscanf (line, "%s %s %s %s %s %s %s %s %s %s",		       when, name, what,		       p[0], p[1], p[2], p[3], p[4], p[5], p[6]);    if (strcasecmp (when, "CLEAR_CONFIG") == 0)    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -