| 709 | } |
| 710 | |
| 711 | static int |
| 712 | prep_devname(struct cdev *dev, const char *fmt, va_list ap) |
| 713 | { |
| 714 | int len; |
| 715 | char *from, *q, *s, *to; |
| 716 | |
| 717 | dev_lock_assert_locked(); |
| 718 | |
| 719 | len = vsnrprintf(dev->si_name, sizeof(dev->si_name), 32, fmt, ap); |
| 720 | if (len > sizeof(dev->si_name) - 1) |
| 721 | return (ENAMETOOLONG); |
| 722 | |
| 723 | /* Strip leading slashes. */ |
| 724 | for (from = dev->si_name; *from == '/'; from++) |
| 725 | ; |
| 726 | |
| 727 | for (to = dev->si_name; *from != '\0'; from++, to++) { |
| 728 | /* |
| 729 | * Spaces and double quotation marks cause |
| 730 | * problems for the devctl(4) protocol. |
| 731 | * Reject names containing those characters. |
| 732 | */ |
| 733 | if (isspace(*from) || *from == '"') |
| 734 | return (EINVAL); |
| 735 | /* Treat multiple sequential slashes as single. */ |
| 736 | while (from[0] == '/' && from[1] == '/') |
| 737 | from++; |
| 738 | /* Trailing slash is considered invalid. */ |
| 739 | if (from[0] == '/' && from[1] == '\0') |
| 740 | return (EINVAL); |
| 741 | *to = *from; |
| 742 | } |
| 743 | *to = '\0'; |
| 744 | |
| 745 | if (dev->si_name[0] == '\0') |
| 746 | return (EINVAL); |
| 747 | |
| 748 | /* Disallow "." and ".." components. */ |
| 749 | for (s = dev->si_name;;) { |
| 750 | for (q = s; *q != '/' && *q != '\0'; q++) |
| 751 | ; |
| 752 | if (q - s == 1 && s[0] == '.') |
| 753 | return (EINVAL); |
| 754 | if (q - s == 2 && s[0] == '.' && s[1] == '.') |
| 755 | return (EINVAL); |
| 756 | if (*q != '/') |
| 757 | break; |
| 758 | s = q + 1; |
| 759 | } |
| 760 | |
| 761 | if (devfs_dev_exists(dev->si_name) != 0) |
| 762 | return (EEXIST); |
| 763 | |
| 764 | return (0); |
| 765 | } |
| 766 | |
| 767 | void |
| 768 | make_dev_args_init_impl(struct make_dev_args *args, size_t sz) |
no test coverage detected