📄 devfsd.c
字号:
unlink (destpath); switch (source_stat->st_mode & S_IFMT) { int fd, val; struct sockaddr_un un_addr; char symlink_val[STRING_LENGTH]; case S_IFSOCK: if ( ( fd = socket (AF_UNIX, SOCK_STREAM, 0) ) < 0 ) break; un_addr.sun_family = AF_UNIX; snprintf (un_addr.sun_path, sizeof (un_addr.sun_path), "%s", destpath); val = bind (fd, (struct sockaddr *) &un_addr, (int) sizeof un_addr); close (fd); if (val != 0) break; if (chmod (destpath, new_mode & ~S_IFMT) != 0) break; if (chown (destpath, source_stat->st_uid, source_stat->st_gid) == 0) return (TRUE); break; case S_IFLNK: if ( ( val = readlink (sourcepath, symlink_val, STRING_LENGTH - 1) ) < 0 ) break; symlink_val[val] = '\0'; if (symlink (symlink_val, destpath) == 0) return (TRUE); break; case S_IFREG: if ( ( fd = open (destpath, O_RDONLY | O_CREAT, new_mode & ~S_IFMT) ) < 0 ) break; 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; 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; case S_IFDIR: if (mkdir (destpath, new_mode & ~S_IFMT) != 0) break; if (chown (destpath, source_stat->st_uid, source_stat->st_gid) == 0) return (TRUE); return (TRUE); /*break;*/ } return (FALSE);} /* End Function copy_inode */static void free_config ()/* [SUMMARY] Free the configuration information. [RETURNS] Nothing.*/{ struct config_entry_struct *c_entry; struct shared_object *so_entry; void *next; for (c_entry = first_config; c_entry != NULL; c_entry = next) { unsigned int count; next = c_entry->next; regfree (&c_entry->preg); if (c_entry->action.what == AC_EXECUTE) { for (count = 0; count < MAX_ARGS; ++count) { if (c_entry->u.execute.argv[count] == NULL) break; free (c_entry->u.execute.argv[count]); } } else if ( (c_entry->action.what == AC_MFUNCTION) || (c_entry->action.what == AC_CFUNCTION) ) { for (count = 0; count < MAX_ARGS; ++count) { if (c_entry->u.function.argv[count] == NULL) break; free (c_entry->u.function.argv[count]); } } free (c_entry); } first_config = NULL; last_config = NULL; for (so_entry = first_so; so_entry != NULL; so_entry = next) { next = so_entry->next; free ( (char *) so_entry->name ); if (so_entry->handle != RTLD_DEFAULT) dlclose (so_entry->handle); free (so_entry); } first_so = NULL;} /* End Function free_config */static void do_debug (int fd)/* [SUMMARY] Debug the devfs protocol. <fd> The open control file. [RETURNS] Nothing.*/{ ssize_t bytes; struct devfsd_notify_struct info; fprintf (stderr, "Running in debug mode: no actions will be taken...\n"); /* Tell devfs what events we care about */ if (ioctl (fd, DEVFSDIOC_SET_EVENT_MASK, ~0) != 0) { SYSLOG (LOG_ERR, "error setting event mask\t%s\n", ERRSTRING); exit (1); } while ( ( bytes = read (fd, (char *) &info, sizeof info) ) >= 0 ) { unsigned int count; CONST char *type = NULL; if (bytes < 1) { fprintf (stderr, "devfs closed file!\n"); exit (1); } if (info.overrun_count > 0) SYSLOG (LOG_ERR, "%u events have been lost!\n",info.overrun_count); for (count = 0; event_types[count].config_name != NULL; ++count) { if (info.type != event_types[count].type) continue; type = event_types[count].debug_name; break; } if (type == NULL) { fprintf (stderr, "Unknown type: %u\n", info.type); exit (1); /*break;*/ } fprintf (stderr, "Entry: \"%s\"(len=%d) %s mode: %o uid: %d gid: %d\n", info.devname, (int) strlen (info.devname), type, (int) info.mode, (int) info.uid, (int) info.gid); } fprintf (stderr, "Error reading control file\t%s\n", ERRSTRING); exit (1);} /* End Function do_debug */static uid_t get_uid (const char *string)/* [SUMMARY] Convert a string to a UID value. <string> The string. [RETURNS] The UID value.*/{ struct passwd *pw_ent; if ( isdigit (string[0]) || ( (string[0] == '-') && isdigit (string[1]) ) ) return atoi (string); if ( ( pw_ent = getpwnam (string) ) == NULL ) { SYSLOG (LOG_ERR, "unknown user: \"%s\", defaulting to UID=0\n", string); return (0); } return (pw_ent->pw_uid);} /* End Function get_uid */static gid_t get_gid (const char *string)/* [SUMMARY] Convert a string to a GID value. <string> The string. [RETURNS] The GID value.*/{ struct group *grp_ent; if ( isdigit (string[0]) || ( (string[0] == '-') && isdigit (string[1]) ) ) return atoi (string); if ( ( grp_ent = getgrnam (string) ) == NULL ) { SYSLOG (LOG_ERR, "unknown group: \"%s\", defaulting to GID=0\n", string); return (0); } return (grp_ent->gr_gid);} /* End Function get_gid */static mode_t get_mode (const char *string)/* [SUMMARY] Convert a string to a mode value. <string> The string. [RETURNS] The mode value.*/{ mode_t mode; if ( isdigit (string[0]) ) return strtoul (string, NULL, 8); if (strlen (string) != 9) { SYSLOG (LOG_ERR, "bad symbolic mode: \"%s\"\n", string); SYSLOG (LOG_ERR, "exiting\n"); exit (1); } 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; if (trace_level > 3) fprintf (stderr, "\tMode \"%s\" gives %05o\n", string, mode); return (mode);} /* End Function get_mode */static void signal_handler (int sig){ caught_signal = TRUE; if (sig == SIGHUP) { caught_sighup = TRUE; SYSLOG (LOG_INFO, "Caught SIGHUP\n"); } else if (sig == SIGUSR1) SYSLOG (LOG_INFO, "Caught SIGUSR1\n");} /* End Function signal_handler */static CONST char *get_variable (CONST char *variable, void *info){ struct get_variable_info *gv_info = info; static flag first_time = TRUE; static char hostname[STRING_LENGTH], sbuf[STRING_LENGTH]; if (first_time) { first_time = FALSE; if (gethostname (hostname, STRING_LENGTH - 1) != 0) { SYSLOG (LOG_ERR, "Error getting hostname\t%s\n", ERRSTRING); exit (RV_SYS_ERROR); } hostname[STRING_LENGTH - 1] = '\0'; } if (strcmp (variable, "hostname") == 0) return (hostname); if (strcmp (variable, "mntpnt") == 0) return (mount_point); if (gv_info == NULL) return (NULL); if (strcmp (variable, "devpath") == 0) return (gv_info->devpath); if (strcmp (variable, "devname") == 0) return (gv_info->devname); if (strcmp (variable, "mode") == 0) { sprintf (sbuf, "%o", gv_info->info->mode); return (sbuf); } if (strcmp (variable, "uid") == 0) { sprintf (sbuf, "%u", gv_info->info->uid); return (sbuf); } if (strcmp (variable, "gid") == 0) { sprintf (sbuf, "%u", gv_info->info->gid); return (sbuf); } return (NULL);} /* End Function get_variable */static void do_open_syslog ()/* [SUMMARY] Open syslog(3) connection if appropriate. [RETURNS] Nothing.*/{ if (syslog_is_open || no_syslog) return; if (access ("/dev/log", F_OK) != 0) return; openlog ("devfsd", LOG_PID, LOG_DAEMON); close (0); close (1); close (2); syslog_is_open = TRUE;} /* End Function do_open_syslog */static void do_scan_and_service (CONST char *dirname)/* [SUMMARY] Scan a directory tree and generate register events on leaf nodes. <dp> The directory pointer. This is closed upon completion. <dirname> The name of the directory. [RETURNS] Nothing.*/{ struct stat statbuf; DIR *dp; struct dirent *de; char path[STRING_LENGTH]; if ( ( dp = opendir (dirname) ) == NULL ) { SYSLOG (LOG_ERR, "Error opening directory \"%s\"\t%s\n", dirname, ERRSTRING); return; } while ( (de = readdir (dp) ) != NULL ) { struct devfsd_notify_struct info; if ( (strcmp (de->d_name, ".") == 0) || (strcmp (de->d_name, "..") == 0) ) continue; snprintf (path, sizeof (path), "%s/%s", dirname, de->d_name); if (lstat (path, &statbuf) != 0) { SYSLOG (LOG_ERR, "Error lstat(2)ing file \"%s\"\t%s\n", path, ERRSTRING); 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); } closedir (dp);} /* End Function do_scan_and_service */int mksymlink (const char *oldpath, const char *newpath)/* [SUMMARY] Create a symlink, creating intervening directories as required. <oldpath> The string contained in the symlink. <newpath> The name of the new symlink. [RETURNS] 0 on success, else -1.*/{ static char function_name[] = "mksymlink"; if ( !make_dir_tree (newpath) ) return (-1); if (symlink (oldpath, newpath) != 0) { if (errno == EEXIST) { if (trace_level > 1) fprintf (stderr, "symlink: \"%s\" already exists\n", newpath); } else { SYSLOG (LOG_ERR, "%s: error creating symlink: \"%s\"\t%s\n", function_name, newpath, ERRSTRING); return (-1); } } return (0);} /* End Function mksymlink */static flag make_dir_tree (const char *path)/* [SUMMARY] Creating intervening directories for a path as required. <path> The full pathname (including he leaf node). [RETURNS] TRUE on success, else FALSE.*/{ char ch; char *ptr1, *ptr2; char path_copy[STRING_LENGTH]; /*static char function_name[] = "make_dir_tree";*/ snprintf (path_copy, sizeof (path_copy), "%s", path); ptr1 = path_copy; while (TRUE) { if ( ( ptr2 = strchr (ptr1 + 1, '/') ) == NULL ) break; ch = *ptr2; *ptr2 = '\0'; if (access (path_copy, F_OK) == 0) { *ptr2 = ch; ptr1 = ptr2; continue; } if (mkdir (path_copy, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { SYSLOG (LOG_ERR, "Error making directory \"%s\"\t%s\n", path_copy, ERRSTRING); *ptr2 = ch; return (FALSE); } *ptr2 = ch; ptr1 = ptr2; } return (TRUE);} /* End Function make_dir_tree */static struct shared_object *get_shared_object (CONST char *name)/* [SUMMARY] Load a shared object if possible. <name> The shared object. [RETURNS] A pointer to the object on success, else NULL.*/{ struct shared_object *so; for (so = first_so; so != NULL; so = so->next) if (strcmp (so->name, name) == 0) return (so); if ( ( so = malloc (sizeof *so) ) == NULL ) return (NULL); if ( ( so->name = strdup (name) ) == NULL ) { free (so); return (NULL); } if (strcmp (name, "GLOBAL") == 0) so->handle = RTLD_DEFAULT; else { char pathname[STRING_LENGTH + 12]; if (name[0] != '/') { /* Default directory is /lib/devfsd */ snprintf (pathname, sizeof pathname, "/lib/devfsd/%s"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -