makedevs.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
  4. *
  5. * makedevs
  6. * Make ranges of device files quickly.
  7. * known bugs: can't deal with alpha ranges
  8. */
  9. #include "busybox.h"
  10. #ifdef CONFIG_FEATURE_MAKEDEVS_LEAF
  11. int makedevs_main(int argc, char **argv)
  12. {
  13. mode_t mode;
  14. char *basedev, *type, *nodname, buf[255];
  15. int Smajor, Sminor, S, E;
  16. if (argc < 7 || *argv[1]=='-')
  17. bb_show_usage();
  18. basedev = argv[1];
  19. type = argv[2];
  20. Smajor = xatoi_u(argv[3]);
  21. Sminor = xatoi_u(argv[4]);
  22. S = xatoi_u(argv[5]);
  23. E = xatoi_u(argv[6]);
  24. nodname = argc == 8 ? basedev : buf;
  25. mode = 0660;
  26. switch (type[0]) {
  27. case 'c':
  28. mode |= S_IFCHR;
  29. break;
  30. case 'b':
  31. mode |= S_IFBLK;
  32. break;
  33. case 'f':
  34. mode |= S_IFIFO;
  35. break;
  36. default:
  37. bb_show_usage();
  38. }
  39. while (S <= E) {
  40. int sz;
  41. sz = snprintf(buf, sizeof(buf), "%s%d", basedev, S);
  42. if(sz<0 || sz>=sizeof(buf)) /* libc different */
  43. bb_error_msg_and_die("%s too large", basedev);
  44. /* if mode != S_IFCHR and != S_IFBLK third param in mknod() ignored */
  45. if (mknod(nodname, mode, makedev(Smajor, Sminor)))
  46. bb_error_msg("failed to create: %s", nodname);
  47. if (nodname == basedev) /* ex. /dev/hda - to /dev/hda1 ... */
  48. nodname = buf;
  49. S++;
  50. Sminor++;
  51. }
  52. return 0;
  53. }
  54. #elif defined CONFIG_FEATURE_MAKEDEVS_TABLE
  55. /* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */
  56. int makedevs_main(int argc, char **argv)
  57. {
  58. FILE *table = stdin;
  59. char *rootdir = NULL;
  60. char *line = NULL;
  61. int linenum = 0;
  62. int ret = EXIT_SUCCESS;
  63. getopt32(argc, argv, "d:", &line);
  64. if (line)
  65. table = xfopen(line, "r");
  66. if (optind >= argc || (rootdir=argv[optind])==NULL) {
  67. bb_error_msg_and_die("root directory not specified");
  68. }
  69. xchdir(rootdir);
  70. umask(0);
  71. printf("rootdir=%s\n", rootdir);
  72. if (line) {
  73. printf("table='%s'\n", line);
  74. } else {
  75. printf("table=<stdin>\n");
  76. }
  77. while ((line = xmalloc_getline(table))) {
  78. char type;
  79. unsigned int mode = 0755;
  80. unsigned int major = 0;
  81. unsigned int minor = 0;
  82. unsigned int count = 0;
  83. unsigned int increment = 0;
  84. unsigned int start = 0;
  85. char name[41];
  86. char user[41];
  87. char group[41];
  88. char *full_name;
  89. uid_t uid;
  90. gid_t gid;
  91. linenum++;
  92. if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name,
  93. &type, &mode, user, group, &major,
  94. &minor, &start, &increment, &count)) ||
  95. ((major | minor | start | count | increment) > 255))
  96. {
  97. if (*line=='\0' || *line=='#' || isspace(*line))
  98. continue;
  99. bb_error_msg("line %d invalid: '%s'", linenum, line);
  100. ret = EXIT_FAILURE;
  101. continue;
  102. }
  103. if (name[0] == '#') {
  104. continue;
  105. }
  106. gid = (*group) ? get_ug_id(group, bb_xgetgrnam) : getgid();
  107. uid = (*user) ? get_ug_id(user, bb_xgetpwnam) : getuid();
  108. full_name = concat_path_file(rootdir, name);
  109. if (type == 'd') {
  110. bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
  111. if (chown(full_name, uid, gid) == -1) {
  112. bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
  113. ret = EXIT_FAILURE;
  114. goto loop;
  115. }
  116. if ((mode != -1) && (chmod(full_name, mode) < 0)){
  117. bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
  118. ret = EXIT_FAILURE;
  119. goto loop;
  120. }
  121. } else if (type == 'f') {
  122. struct stat st;
  123. if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) {
  124. bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name);
  125. ret = EXIT_FAILURE;
  126. goto loop;
  127. }
  128. if (chown(full_name, uid, gid) == -1) {
  129. bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
  130. ret = EXIT_FAILURE;
  131. goto loop;
  132. }
  133. if ((mode != -1) && (chmod(full_name, mode) < 0)){
  134. bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
  135. ret = EXIT_FAILURE;
  136. goto loop;
  137. }
  138. } else
  139. {
  140. dev_t rdev;
  141. if (type == 'p') {
  142. mode |= S_IFIFO;
  143. }
  144. else if (type == 'c') {
  145. mode |= S_IFCHR;
  146. }
  147. else if (type == 'b') {
  148. mode |= S_IFBLK;
  149. } else {
  150. bb_error_msg("line %d: unsupported file type %c", linenum, type);
  151. ret = EXIT_FAILURE;
  152. goto loop;
  153. }
  154. if (count > 0) {
  155. int i;
  156. char *full_name_inc;
  157. full_name_inc = xmalloc(strlen(full_name) + 4);
  158. for (i = start; i < count; i++) {
  159. sprintf(full_name_inc, "%s%d", full_name, i);
  160. rdev = (major << 8) + minor + (i * increment - start);
  161. if (mknod(full_name_inc, mode, rdev) == -1) {
  162. bb_perror_msg("line %d: cannot create node %s", linenum, full_name_inc);
  163. ret = EXIT_FAILURE;
  164. }
  165. else if (chown(full_name_inc, uid, gid) == -1) {
  166. bb_perror_msg("line %d: chown failed for %s", linenum, full_name_inc);
  167. ret = EXIT_FAILURE;
  168. }
  169. if ((mode != -1) && (chmod(full_name_inc, mode) < 0)){
  170. bb_perror_msg("line %d: chmod failed for %s", linenum, full_name_inc);
  171. ret = EXIT_FAILURE;
  172. }
  173. }
  174. free(full_name_inc);
  175. } else {
  176. rdev = (major << 8) + minor;
  177. if (mknod(full_name, mode, rdev) == -1) {
  178. bb_perror_msg("line %d: cannot create node %s", linenum, full_name);
  179. ret = EXIT_FAILURE;
  180. }
  181. else if (chown(full_name, uid, gid) == -1) {
  182. bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
  183. ret = EXIT_FAILURE;
  184. }
  185. if ((mode != -1) && (chmod(full_name, mode) < 0)){
  186. bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
  187. ret = EXIT_FAILURE;
  188. }
  189. }
  190. }
  191. loop:
  192. free(line);
  193. free(full_name);
  194. }
  195. fclose(table);
  196. return ret;
  197. }
  198. #else
  199. # error makedevs configuration error, either leaf or table must be selected
  200. #endif