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

📄 devfsd.c

📁 devfsd 驱动对linux的补丁支持
💻 C
📖 第 1 页 / 共 5 页
字号:
    argv[0] = "/sbin/modprobe";    argv[1] = "-k";    argv[2] = "-C";    argv[3] = "/etc/modules.devfs";    argv[4] = device;    argv[5] = NULL;    snprintf (device, sizeof (device), "/dev/%s", info->devname);    if (trace_level > 1)	fprintf (stderr, "%s modprobe with name: \"%s\"\n",		 modprobe ? "Calling" : "Executing", device);    if (modprobe != NULL)    {	char **oldenv = environ;	environ = env;	(*modprobe) (5, argv);	environ = oldenv;	return;    }    switch ( fork () )    {      case 0:	/*  Child  */	break;      case -1:	/*  Error  */	SYSLOG (LOG_ERR, "error forking\t%s\n", ERRSTRING);	exit (2);	/*break;*/      default:	/*  Parent  */	wait (NULL);	return;	/*break;*/    }    environ = env;    execvp (argv[0], argv);    SYSLOG (LOG_ERR, "error execing: \"%s\"\t%s\n", argv[0], ERRSTRING);    _exit (1);}   /*  End Function action_modload  */static void action_execute (const struct devfsd_notify_struct *info,			    const struct config_entry_struct *entry,			    const regmatch_t *regexpr, unsigned int numexpr)/*  [SUMMARY] Execute a programme.    <info> The devfs change.    <entry> The config file entry.    <regexpr> The number of subexpression (start, end) offsets within the    device name.    <numexpr> The number of elements within <<regexpr>>.    [RETURNS] Nothing.*/{    unsigned int count;    struct get_variable_info gv_info;    char *argv[MAX_ARGS + 1];    char largv[MAX_ARGS + 1][STRING_LENGTH];    gv_info.info = info;    gv_info.devname = info->devname;    snprintf (gv_info.devpath, sizeof (gv_info.devpath), "%s/%s",	      mount_point, info->devname);    if (trace_level > 1) fprintf (stderr, "Calling %s for \"%s\" | \"%s\":",				  entry->u.execute.argv[0], info->devname,				  gv_info.devpath);    for (count = 0; entry->u.execute.argv[count] != NULL; ++count)    {	expand_expression (largv[count], STRING_LENGTH,			   entry->u.execute.argv[count],			   get_variable, &gv_info,			   gv_info.devname, regexpr, numexpr, NULL);	argv[count] = largv[count];	if (trace_level > 1) fprintf (stderr, " '%s'", argv[count]);    }    if (trace_level > 1) fprintf (stderr, ". i.e. %d arg%s\n",				  count - 1, (count == 2) ? "" : "s");    argv[count] = NULL;    switch ( fork () )    {      case 0:	/*  Child  */	break;      case -1:	/*  Error  */	SYSLOG (LOG_ERR, "error forking for programme: %s\t%s\n",		argv[0], ERRSTRING);	return;	/*break;*/      default:	/*  Parent  */	wait (NULL);	return;	/*break;*/    }    execvp (argv[0], argv);    SYSLOG (LOG_ERR, "error execing: \"%s\"\t%s\n", argv[0], ERRSTRING);    _exit (1);}   /*  End Function action_execute  */static void action_call_function (const struct devfsd_notify_struct *info,				  const struct config_entry_struct *entry,				  const regmatch_t *regexpr,				  unsigned int numexpr)/*  [SUMMARY] Call a function.    <info> The devfs change.    <entry> The config file entry.    <regexpr> The number of subexpression (start, end) offsets within the    device name.    <numexpr> The number of elements within <<regexpr>>.    [RETURNS] Nothing.*/{    unsigned int count;    struct get_variable_info gv_info;    char *argv[MAX_ARGS + 1];    char largv[MAX_ARGS + 1][STRING_LENGTH];    gv_info.info = info;    gv_info.devname = info->devname;    snprintf (gv_info.devpath, sizeof (gv_info.devpath), "%s/%s",	      mount_point, info->devname);    if (trace_level > 1)	fprintf (stderr, "Calling %s in %s for \"%s\" | \"%s\":",		 entry->u.function.argv[0], entry->u.function.so->name,		 info->devname, gv_info.devpath);    argv[0] = (char *) entry->u.function.so->name;    for (count = 1; entry->u.function.argv[count] != NULL; ++count)    {	if (strcmp (entry->u.function.argv[count], "EVENT") == 0)	    argv[count] = (char *) info;	else	{	    expand_expression (largv[count], STRING_LENGTH,			       entry->u.function.argv[count], get_variable,			       &gv_info, gv_info.devname, regexpr, numexpr,			       NULL);	    argv[count] = largv[count];	    if (trace_level > 1) fprintf (stderr, " '%s'", argv[count]);	}    }    if (trace_level > 1) fprintf (stderr, ". i.e. %d arg%s\n",				  count - 1, (count == 2) ? "" : "s");    argv[count] = NULL;    if (entry->action.what == AC_MFUNCTION)    {	if ( (*entry->u.function.func.m) (count, argv) == 0 )	    return;    }    else    {	if ( (*entry->u.function.func.c) (argv[1], argv[2], argv[3], argv[4],					  argv[5]) == 0 ) return;    }    SYSLOG (LOG_ERR, "error calling: \"%s\" in \"%s\"\n",	    entry->u.function.argv[0], argv[0]);}   /*  End Function action_call_function  */static void action_copy (const struct devfsd_notify_struct *info,			 const struct config_entry_struct *entry,                         const regmatch_t *regexpr, unsigned int numexpr)/*  [SUMMARY] Copy permissions.    <info> The devfs change.    <entry> The config file entry.    <regexpr> This list of subexpression (start, end) offsets within the    device name.    <numexpr> The number of elements in <<regexpr>>.      [RETURNS] Nothing.*/{    mode_t new_mode;    struct get_variable_info gv_info;    struct stat source_stat, dest_stat;    char source[STRING_LENGTH], destination[STRING_LENGTH];    if ( (info->type == DEVFSD_NOTIFY_CHANGE) && S_ISLNK (info->mode) ) return;    gv_info.info = info;    gv_info.devname = info->devname;    snprintf (gv_info.devpath, sizeof (gv_info.devpath), "%s/%s",	      mount_point, info->devname);    expand_expression (source, STRING_LENGTH, entry->u.copy.source,		       get_variable, &gv_info, gv_info.devname,		       regexpr, numexpr, NULL);    expand_expression (destination, STRING_LENGTH, entry->u.copy.destination,		       get_variable, &gv_info, gv_info.devname,		       regexpr, numexpr, NULL);    if (trace_level > 1)	fprintf (stderr, "Copying %s to %s for \"%s\" | \"%s\"\n",		 source, destination, info->devname, gv_info.devpath);    if ( !make_dir_tree (destination) )    {	SYSLOG (LOG_ERR, "error making tree for: \"%s\"\n", destination);	return;    }    if (lstat (source, &source_stat) != 0) return;    if (lstat (destination, &dest_stat) != 0) dest_stat.st_mode = 0;    new_mode = source_stat.st_mode & ~S_ISVTX;    if (info->type == DEVFSD_NOTIFY_CREATE) new_mode |= S_ISVTX;    else if ( (info->type == DEVFSD_NOTIFY_CHANGE) &&	      (dest_stat.st_mode & S_ISVTX) ) new_mode |= S_ISVTX;    if ( !copy_inode (destination, &dest_stat, new_mode, source,&source_stat) )	SYSLOG (LOG_ERR, "error copying: \"%s\" to \"%s\"\n",		source, destination);}   /*  End Function action_copy  */static void action_compat (const struct devfsd_notify_struct *info,			   unsigned int action)/*  [SUMMARY] Process a compatibility request.    <info> The devfs change.    <action> The action to take.    [RETURNS] Nothing.*/{    const char *compat_name = NULL;    const char *dest_name = info->devname;    char *ptr;    char compat_buf[STRING_LENGTH], dest_buf[STRING_LENGTH];    static char function_name[] = "action_compat";    /*  First construct compatibility name  */    switch (action)    {      case AC_MKOLDCOMPAT:      case AC_RMOLDCOMPAT:	compat_name = get_old_name (info->devname, info->namelen, compat_buf,				    info->major, info->minor);	break;      case AC_MKNEWCOMPAT:      case AC_RMNEWCOMPAT:	if (strncmp (info->devname, "scsi/", 5) == 0)	{	    int mode, host, bus, target, lun;	    sscanf (info->devname + 5, "host%d/bus%d/target%d/lun%d/",		    &host, &bus, &target, &lun);	    compat_name = compat_buf;	    snprintf (dest_buf, sizeof (dest_buf), "../%s", info->devname);	    dest_name = dest_buf;	    if (strncmp (ptr = (strrchr (info->devname, '/') + 1), "mt", 2)		== 0)	    {		char rewind = info->devname[info->namelen - 1];		if (rewind != 'n') rewind = '\0';		switch (ptr[2])		{		  default:		    mode = 0;		    break;		  case 'l':		    mode = 1;		    break;		  case 'm':		    mode = 2;		    break;		  case 'a':		    mode = 3;		    break;		}		sprintf (compat_buf, "st/c%db%dt%du%dm%d%c",			 host, bus, target, lun, mode, rewind);	    }	    else if (strcmp (info->devname + info->namelen - 7,"generic") == 0)		sprintf (compat_buf, "sg/c%db%dt%du%d",			 host, bus, target, lun);	    else if (strcmp (info->devname + info->namelen - 2, "cd") == 0)		sprintf (compat_buf, "sr/c%db%dt%du%d",			 host, bus, target, lun);	    else if (strcmp (info->devname + info->namelen - 4, "disc") == 0)		sprintf (compat_buf, "sd/c%db%dt%du%d",			 host, bus, target, lun);	    else if (strncmp (ptr = (strrchr (info->devname, '/') + 1), "part",			      4) == 0)		sprintf ( compat_buf, "sd/c%db%dt%du%dp%d",			  host, bus, target, lun, atoi (ptr + 4) );	    else compat_name = NULL;	}	else if (strncmp (info->devname, "ide/host", 8) == 0)	{	    int host, bus, target, lun;	    sscanf (info->devname + 4, "host%d/bus%d/target%d/lun%d/",		    &host, &bus, &target, &lun);	    compat_name = compat_buf;	    snprintf (dest_buf, sizeof (dest_buf), "../%s", info->devname + 4);	    dest_name = dest_buf;	    if (strcmp (info->devname + info->namelen - 4, "disc") == 0)		sprintf (compat_buf, "ide/hd/c%db%dt%du%d",			 host, bus, target, lun);	    else if (strncmp (ptr = (strrchr (info->devname, '/') + 1), "part",			      4) == 0)		sprintf ( compat_buf, "ide/hd/c%db%dt%du%dp%d",			  host, bus, target, lun, atoi (ptr + 4) );	    else if (strcmp (info->devname + info->namelen - 2, "cd") == 0)		sprintf (compat_buf, "ide/cd/c%db%dt%du%d",			 host, bus, target,lun);	    else if (strncmp (ptr = (strrchr (info->devname, '/') + 1), "mt",			      2) == 0)		snprintf (compat_buf, sizeof (compat_buf),			  "ide/mt/c%db%dt%du%d%s",			  host, bus, target, lun, ptr + 2);	    else compat_name = NULL;	}	break;    }    if (compat_name == NULL) return;    /*  Now decide what to do with it  */    switch (action)    {      case AC_MKOLDCOMPAT:      case AC_MKNEWCOMPAT:	if (mksymlink (dest_name, compat_name) == 0)	    if (trace_level > 1)		fprintf (stderr, "made symlink: \"%s\" for dev: %u,%u\n",			compat_name, info->major, info->minor);	break;      case AC_RMOLDCOMPAT:      case AC_RMNEWCOMPAT:	if (unlink (compat_name) != 0)	{	    SYSLOG (LOG_ERR, "%s: error unlinking: \"%s\"\t%s\n",		    function_name, compat_name, ERRSTRING);	}	else if (trace_level > 1)	    fprintf (stderr, "unlinked: \"%s\"\n", compat_name);	break;    }}   /*  End Function action_compat  */static void do_restore (const char *dirname, int rootlen)/*  [SUMMARY] Restore state from a directory.    <dirname> The directory containing the backing store.    <rootlen> The length of the root of the state directory hierarchy.    [RETURNS] Nothing.*/{    DIR *dp;    struct dirent *de;    if ( ( dp = opendir (dirname) ) == NULL )    {	SYSLOG (LOG_ERR, "Error opening directory \"%s\"\t%s\n",		dirname, ERRSTRING);	return;    }    while ( (de = readdir (dp) ) != NULL )    {	mode_t new_mode;	struct stat source_stat, dest_stat;	char spath[STRING_LENGTH], dpath[STRING_LENGTH];	if ( (strcmp (de->d_name, ".") == 0) ||	     (strcmp (de->d_name, "..") == 0) ) continue;	snprintf (spath, sizeof spath, "%s/%s", dirname, de->d_name);	if (lstat (spath, &source_stat) != 0)	{	    SYSLOG (LOG_ERR, "Error lstat(2)ing file \"%s\"\t%s\n",		    spath, ERRSTRING);	    continue;	}	snprintf (dpath, sizeof dpath, "%s%s", mount_point, spath + rootlen);	if (lstat (dpath, &dest_stat) != 0) dest_stat.st_mode = 0;	new_mode = source_stat.st_mode & ~S_ISVTX;	if ( S_ISLNK (source_stat.st_mode) || (source_stat.st_mode & S_ISVTX) )	    copy_inode (dpath, &dest_stat, new_mode, spath, &source_stat);	if ( S_ISDIR (source_stat.st_mode) ) do_restore (spath, rootlen);    }    closedir (dp);}   /*  End Function do_restore  */static flag copy_inode (const char *destpath, const struct stat *dest_stat,			mode_t new_mode,			const char *sourcepath, const struct stat *source_stat)/*  [SUMMARY] Copy an inode.    <destpath> The destination path. An existing inode may be deleted.    <dest_stat> The destination stat(2) information.    <new_mode> The desired new mode for the destination.    <sourcepath> The source path.    <source_stat> The source stat(2) information.    [RETURNS] TRUE on success, else FALSE.*/{    if ( (source_stat->st_mode & S_IFMT) == (dest_stat->st_mode & S_IFMT) )    {	/*  Same type  */	if ( S_ISLNK (source_stat->st_mode) )	{	    int source_len, dest_len;	    char source_link[STRING_LENGTH], dest_link[STRING_LENGTH];	    if ( ( source_len = readlink (sourcepath, source_link,					  STRING_LENGTH - 1) ) < 0 )		return (FALSE);	    source_link[source_len] = '\0';	    if ( ( dest_len = readlink (destpath, dest_link,					STRING_LENGTH - 1) ) < 0 )		return (FALSE);	    dest_link[dest_len] = '\0';	    if ( (source_len != dest_len) ||		 (strcmp (source_link, dest_link) != 0) )	    {		unlink (destpath);		symlink (source_link, destpath);	    }	    return (TRUE);	}   /*  Else not a symlink  */	if (new_mode != dest_stat->st_mode)	    chmod (destpath, new_mode & ~S_IFMT);	if ( (source_stat->st_uid != dest_stat->st_uid) ||	     (source_stat->st_gid != dest_stat->st_gid) )	    chown (destpath, source_stat->st_uid, source_stat->st_gid);	return (TRUE);    }    /*  Different types: unlink and create  */

⌨️ 快捷键说明

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