logo

utils-std

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

mkdir.c (2269B)


  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/getopt_nolong.h"
  6. #include "../lib/lib_mkdir.h"
  7. #include "../lib/mode.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. if(mkdir(path, mode) < 0)
  22. {
  23. fprintf(stderr, "%s: error: Failed making directory '%s': %s\n", argv0, path, strerror(errno));
  24. errno = 0;
  25. return -1;
  26. }
  27. if(mkdir_parents_verbose) fprintf(stderr, "%s: Made directory: %s\n", argv0, path);
  28. return 0;
  29. }
  30. static void
  31. usage(void)
  32. {
  33. fprintf(stderr, "Usage: mkdir [-pv] [-m mode] path ...\n");
  34. }
  35. int
  36. main(int argc, char *argv[])
  37. {
  38. mkdir_parents_filemask = umask(0);
  39. umask(mkdir_parents_filemask);
  40. // clang-format off
  41. mode_t mode = (S_IRWXU | S_IRWXG | S_IRWXO | ~mkdir_parents_filemask) & 0777;
  42. bool opt_p = false;
  43. const char *errstr = NULL;
  44. // clang-format on
  45. for(int c = -1; (c = getopt_nolong(argc, argv, ":pvm:")) != -1;)
  46. {
  47. switch(c)
  48. {
  49. case 'p':
  50. opt_p = true;
  51. break;
  52. case 'v':
  53. mkdir_parents_verbose = true;
  54. break;
  55. case 'm':
  56. mode = new_mode(optarg, 0777, &errstr);
  57. if(errstr != NULL)
  58. {
  59. fprintf(stderr, "%s: error: Failed parsing mode '%s': %s\n", argv0, optarg, errstr);
  60. return 1;
  61. }
  62. break;
  63. case ':':
  64. fprintf(stderr, "%s: error: Missing operand for option: '-%c'\n", argv0, optopt);
  65. usage();
  66. return 1;
  67. case '?':
  68. if(!got_long_opt) fprintf(stderr, "%s: error: Unrecognised option: '-%c'\n", argv0, optopt);
  69. usage();
  70. return 1;
  71. default:
  72. abort();
  73. }
  74. }
  75. argc -= optind;
  76. argv += optind;
  77. if(argc < 1)
  78. {
  79. fprintf(stderr, "%s: error: Missing operand\n", argv0);
  80. usage();
  81. return 1;
  82. }
  83. for(int i = 0; i < argc; i++)
  84. {
  85. int ret = 0;
  86. if(opt_p)
  87. ret = mkdir_parents(argv[i], mode);
  88. else
  89. ret = mkdir_simple(argv[i], mode);
  90. if(ret < 0) return 1;
  91. }
  92. return 0;
  93. }