makedevs.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /* vi: set sw=4 ts=4: */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <fcntl.h>
  6. #include <getopt.h>
  7. #include <time.h>
  8. #include <unistd.h>
  9. #include <sys/types.h>
  10. #include <sys/sysmacros.h> /* major() and minor() */
  11. #include "busybox.h"
  12. #ifdef CONFIG_FEATURE_MAKEDEVS_LEAF
  13. /*
  14. * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
  15. *
  16. * makedevs
  17. * Make ranges of device files quickly.
  18. * known bugs: can't deal with alpha ranges
  19. */
  20. int makedevs_main(int argc, char **argv)
  21. {
  22. mode_t mode;
  23. char *basedev, *type, *nodname, buf[255];
  24. int Smajor, Sminor, S, E;
  25. if (argc < 7 || *argv[1]=='-')
  26. bb_show_usage();
  27. basedev = argv[1];
  28. type = argv[2];
  29. Smajor = atoi(argv[3]);
  30. Sminor = atoi(argv[4]);
  31. S = atoi(argv[5]);
  32. E = atoi(argv[6]);
  33. nodname = argc == 8 ? basedev : buf;
  34. mode = 0660;
  35. switch (type[0]) {
  36. case 'c':
  37. mode |= S_IFCHR;
  38. break;
  39. case 'b':
  40. mode |= S_IFBLK;
  41. break;
  42. case 'f':
  43. mode |= S_IFIFO;
  44. break;
  45. default:
  46. bb_show_usage();
  47. }
  48. while (S <= E) {
  49. int sz;
  50. sz = snprintf(buf, sizeof(buf), "%s%d", basedev, S);
  51. if(sz<0 || sz>=sizeof(buf)) /* libc different */
  52. bb_error_msg_and_die("%s too large", basedev);
  53. /* if mode != S_IFCHR and != S_IFBLK third param in mknod() ignored */
  54. if (mknod(nodname, mode, makedev(Smajor, Sminor)))
  55. bb_error_msg("Failed to create: %s", nodname);
  56. if (nodname == basedev) /* ex. /dev/hda - to /dev/hda1 ... */
  57. nodname = buf;
  58. S++;
  59. Sminor++;
  60. }
  61. return 0;
  62. }
  63. #elif defined CONFIG_FEATURE_MAKEDEVS_TABLE
  64. /*
  65. * This program is free software; you can redistribute it and/or modify
  66. * it under the terms of the GNU General Public License version 2 as
  67. * published by the Free Software Foundation.
  68. *
  69. * This program is distributed in the hope that it will be useful,
  70. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  71. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  72. * GNU Library General Public License for more details.
  73. *
  74. * You should have received a copy of the GNU General Public License
  75. * along with this program; if not, write to the Free Software
  76. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  77. *
  78. */
  79. static const struct option makedevs_long_options[] = {
  80. {"root", 1, NULL, 'r'},
  81. {0, 0, 0, 0}
  82. };
  83. extern int makedevs_main(int argc, char **argv)
  84. {
  85. FILE *table;
  86. int opt;
  87. char *rootdir = "./";
  88. char *line;
  89. int ret = EXIT_SUCCESS;
  90. bb_opt_complementaly = "d~r";
  91. bb_applet_long_options = makedevs_long_options;
  92. opt = bb_getopt_ulflags(argc, argv, "d:r:", &rootdir, &rootdir);
  93. if (optind + 1 == argc) {
  94. table = bb_xfopen(argv[optind], "r");
  95. } else {
  96. table = stdin;
  97. }
  98. if (chdir(rootdir) == -1) {
  99. bb_perror_msg_and_die("Couldnt chdor to %s", rootdir);
  100. }
  101. umask(0);
  102. while ((line = bb_get_chomped_line_from_file(table))) {
  103. char type;
  104. unsigned int mode = 0755;
  105. unsigned int major = 0;
  106. unsigned int minor = 0;
  107. unsigned int count = 0;
  108. unsigned int increment = 0;
  109. unsigned int start = 0;
  110. char name[41];
  111. char user[41];
  112. char group[41];
  113. char *full_name;
  114. uid_t uid;
  115. gid_t gid;
  116. if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name,
  117. &type, &mode, user, group, &major,
  118. &minor, &start, &increment, &count)) ||
  119. ((major | minor | start | count | increment) > 255)) {
  120. bb_error_msg("Ignoring invalid line\n%s\n", line);
  121. ret = EXIT_FAILURE;
  122. continue;
  123. }
  124. if (name[0] == '#') {
  125. continue;
  126. }
  127. if (group) {
  128. gid = get_ug_id(group, my_getgrnam);
  129. } else {
  130. gid = getgid();
  131. }
  132. if (user) {
  133. uid = get_ug_id(user, my_getpwnam);
  134. } else {
  135. uid = getuid();
  136. }
  137. full_name = concat_path_file(rootdir, name);
  138. if (type == 'd') {
  139. bb_make_directory(full_name, mode | S_IFDIR, 0);
  140. if (chown(full_name, uid, gid) == -1) {
  141. bb_perror_msg("chown failed for %s", full_name);
  142. ret = EXIT_FAILURE;
  143. goto loop;
  144. }
  145. } else {
  146. dev_t rdev;
  147. if (type == 'p') {
  148. mode |= S_IFIFO;
  149. }
  150. else if (type == 'c') {
  151. mode |= S_IFCHR;
  152. }
  153. else if (type == 'b') {
  154. mode |= S_IFBLK;
  155. } else {
  156. bb_error_msg("Unsupported file type %c", type);
  157. ret = EXIT_FAILURE;
  158. goto loop;
  159. }
  160. if (count > 0) {
  161. int i;
  162. char *full_name_inc;
  163. full_name_inc = xmalloc(strlen(full_name) + 4);
  164. for (i = start; i < count; i++) {
  165. sprintf(full_name_inc, "%s%d", full_name, i);
  166. rdev = (major << 8) + minor + (i * increment - start);
  167. if (mknod(full_name_inc, mode, rdev) == -1) {
  168. bb_perror_msg("Couldnt create node %s", full_name_inc);
  169. ret = EXIT_FAILURE;
  170. }
  171. else if (chown(full_name_inc, uid, gid) == -1) {
  172. bb_perror_msg("chown failed for %s", full_name_inc);
  173. ret = EXIT_FAILURE;
  174. }
  175. }
  176. free(full_name_inc);
  177. } else {
  178. rdev = (major << 8) + minor;
  179. if (mknod(full_name, mode, rdev) == -1) {
  180. bb_perror_msg("Couldnt create node %s", full_name);
  181. ret = EXIT_FAILURE;
  182. }
  183. else if (chown(full_name, uid, gid) == -1) {
  184. bb_perror_msg("chown failed for %s", full_name);
  185. ret = EXIT_FAILURE;
  186. }
  187. }
  188. }
  189. loop:
  190. free(line);
  191. free(full_name);
  192. }
  193. fclose(table);
  194. return 0;
  195. }
  196. #else
  197. # error makdedevs configuration error, either leaf or table must be selected
  198. #endif