makedevs.c 5.6 KB

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