logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git

mkdir.c (2227B)


  1. // utils-std: Collection of commonly available Unix tools
  2. // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #include "../lib/mkdir.h"
  6. #include "../lib/mode.h"
  7. #include <assert.h>
  8. #include <errno.h>
  9. #include <stdbool.h>
  10. #include <stdio.h> // fprintf
  11. #include <stdlib.h> // abort
  12. #include <string.h> // strerror
  13. #include <sys/stat.h> // mkdir
  14. #include <unistd.h> // getopt
  15. const char *argv0 = "mkdir";
  16. bool mkdir_parents_verbose = false;
  17. mode_t mkdir_parents_filemask;
  18. static int
  19. mkdir_simple(char *path, mode_t mode)
  20. {
  21. assert(errno == 0);
  22. if(mkdir(path, mode) < 0)
  23. {
  24. fprintf(stderr, "mkdir: Failed making directory '%s': %s\n", path, strerror(errno));
  25. errno = 0;
  26. return -1;
  27. }
  28. if(mkdir_parents_verbose) fprintf(stderr, "mkdir: Made directory: %s\n", path);
  29. return 0;
  30. }
  31. static void
  32. usage(void)
  33. {
  34. fprintf(stderr, "Usage: mkdir [-pv] [-m mode] path ...\n");
  35. }
  36. int
  37. main(int argc, char *argv[])
  38. {
  39. mkdir_parents_filemask = umask(0);
  40. umask(mkdir_parents_filemask);
  41. // clang-format off
  42. mode_t mode = (S_IRWXU | S_IRWXG | S_IRWXO | ~mkdir_parents_filemask) & 0777;
  43. bool opt_p = false;
  44. const char *errstr = NULL;
  45. // clang-format on
  46. int c = -1;
  47. while((c = getopt(argc, argv, ":pvm:")) != -1)
  48. {
  49. switch(c)
  50. {
  51. case 'p':
  52. opt_p = true;
  53. break;
  54. case 'v':
  55. mkdir_parents_verbose = true;
  56. break;
  57. case 'm':
  58. mode = new_mode(optarg, 0777, &errstr);
  59. if(errstr != NULL)
  60. {
  61. fprintf(stderr, "mkdir: Failed parsing mode '%s': %s\n", optarg, errstr);
  62. return 1;
  63. }
  64. break;
  65. case ':':
  66. fprintf(stderr, "mkdir: Error: Missing operand for option: '-%c'\n", optopt);
  67. usage();
  68. return 1;
  69. case '?':
  70. fprintf(stderr, "mkdir: Error: Unrecognised option: '-%c'\n", optopt);
  71. usage();
  72. return 1;
  73. default:
  74. abort();
  75. }
  76. }
  77. argc -= optind;
  78. argv += optind;
  79. assert(errno == 0);
  80. if(argc < 1)
  81. {
  82. fprintf(stderr, "mkdir: Missing operand\n");
  83. usage();
  84. return 1;
  85. }
  86. for(int i = 0; i < argc; i++)
  87. {
  88. int ret = 0;
  89. if(opt_p)
  90. ret = mkdir_parents(argv[i], mode);
  91. else
  92. ret = mkdir_simple(argv[i], mode);
  93. if(ret < 0) return 1;
  94. }
  95. return 0;
  96. }