PageRenderTime 57ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/lib/libcmd/common/mkdir.c

https://bitbucket.org/illumos/illumos-gate/
C | 181 lines | 142 code | 7 blank | 32 comment | 43 complexity | 2ac31609a29d1c7636ae0ff3a9ff60bb MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, AGPL-1.0, AGPL-3.0, BSD-3-Clause, GPL-3.0, LGPL-2.1, BSD-2-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, 0BSD
  1. /***********************************************************************
  2. * *
  3. * This software is part of the ast package *
  4. * Copyright (c) 1992-2010 AT&T Intellectual Property *
  5. * and is licensed under the *
  6. * Common Public License, Version 1.0 *
  7. * by AT&T Intellectual Property *
  8. * *
  9. * A copy of the License is available at *
  10. * http://www.opensource.org/licenses/cpl1.0.txt *
  11. * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
  12. * *
  13. * Information and Software Systems Research *
  14. * AT&T Research *
  15. * Florham Park NJ *
  16. * *
  17. * Glenn Fowler <gsf@research.att.com> *
  18. * David Korn <dgk@research.att.com> *
  19. * *
  20. ***********************************************************************/
  21. #pragma prototyped
  22. /*
  23. * David Korn
  24. * AT&T Bell Laboratories
  25. *
  26. * mkdir
  27. */
  28. static const char usage[] =
  29. "[-?\n@(#)$Id: mkdir (AT&T Research) 2009-12-03 $\n]"
  30. USAGE_LICENSE
  31. "[+NAME?mkdir - make directories]"
  32. "[+DESCRIPTION?\bmkdir\b creates one or more directories. By "
  33. "default, the mode of created directories is \ba=rwx\b minus the "
  34. "bits set in the \bumask\b(1).]"
  35. "[m:mode]:[mode?Set the mode of created directories to \amode\a. "
  36. "\amode\a is symbolic or octal mode as in \bchmod\b(1). Relative "
  37. "modes assume an initial mode of \ba=rwx\b.]"
  38. "[p:parents?Create any missing intermediate pathname components. For "
  39. "each dir operand that does not name an existing directory, effects "
  40. "equivalent to those caused by the following command shall occur: "
  41. "\vmkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode]] "
  42. "dir\v where the \b-m\b mode option represents that option supplied to "
  43. "the original invocation of \bmkdir\b, if any. Each dir operand that "
  44. "names an existing directory shall be ignored without error.]"
  45. "[v:verbose?Print a message on the standard error for each created "
  46. "directory.]"
  47. "\n"
  48. "\ndirectory ...\n"
  49. "\n"
  50. "[+EXIT STATUS?]{"
  51. "[+0?All directories created successfully, or the \b-p\b option "
  52. "was specified and all the specified directories now exist.]"
  53. "[+>0?An error occurred.]"
  54. "}"
  55. "[+SEE ALSO?\bchmod\b(1), \brmdir\b(1), \bumask\b(1)]"
  56. ;
  57. #include <cmd.h>
  58. #include <ls.h>
  59. #define DIRMODE (S_IRWXU|S_IRWXG|S_IRWXO)
  60. int
  61. b_mkdir(int argc, char** argv, void* context)
  62. {
  63. register char* arg;
  64. register int n;
  65. register mode_t mode = DIRMODE;
  66. register mode_t mask = 0;
  67. register int mflag = 0;
  68. register int pflag = 0;
  69. register int vflag = 0;
  70. char* name;
  71. mode_t dmode;
  72. struct stat st;
  73. cmdinit(argc, argv, context, ERROR_CATALOG, 0);
  74. for (;;)
  75. {
  76. switch (optget(argv, usage))
  77. {
  78. case 0:
  79. break;
  80. case 'm':
  81. mflag = 1;
  82. mode = strperm(arg = opt_info.arg, &opt_info.arg, mode);
  83. if (*opt_info.arg)
  84. error(ERROR_exit(0), "%s: invalid mode", arg);
  85. continue;
  86. case 'p':
  87. pflag = 1;
  88. continue;
  89. case 'v':
  90. vflag = 1;
  91. continue;
  92. case ':':
  93. error(2, "%s", opt_info.arg);
  94. continue;
  95. case '?':
  96. error(ERROR_usage(2), "%s", opt_info.arg);
  97. continue;
  98. }
  99. break;
  100. }
  101. argv += opt_info.index;
  102. if (error_info.errors || !*argv)
  103. error(ERROR_usage(2), "%s", optusage(NiL));
  104. mask = umask(0);
  105. if (mflag || pflag)
  106. {
  107. dmode = DIRMODE & ~mask;
  108. if (!mflag)
  109. mode = dmode;
  110. dmode |= S_IWUSR | S_IXUSR;
  111. }
  112. else
  113. {
  114. mode &= ~mask;
  115. umask(mask);
  116. mask = 0;
  117. }
  118. while (arg = *argv++)
  119. {
  120. if (mkdir(arg, mode) < 0)
  121. {
  122. if (!pflag || !(errno == ENOENT || errno == EEXIST || errno == ENOTDIR))
  123. {
  124. error(ERROR_system(0), "%s:", arg);
  125. continue;
  126. }
  127. if (errno == EEXIST)
  128. continue;
  129. /*
  130. * -p option, preserve intermediates
  131. * first eliminate trailing /'s
  132. */
  133. n = strlen(arg);
  134. while (n > 0 && arg[--n] == '/');
  135. arg[n + 1] = 0;
  136. for (name = arg, n = *arg; n;)
  137. {
  138. /* skip over slashes */
  139. while (*arg == '/')
  140. arg++;
  141. /* skip to next component */
  142. while ((n = *arg) && n != '/')
  143. arg++;
  144. *arg = 0;
  145. if (mkdir(name, n ? dmode : mode) < 0 && errno != EEXIST && access(name, F_OK) < 0)
  146. {
  147. *arg = n;
  148. error(ERROR_system(0), "%s:", name);
  149. break;
  150. }
  151. if (vflag)
  152. error(0, "%s: directory created", name);
  153. if (!(*arg = n) && (mode & (S_ISVTX|S_ISUID|S_ISGID)))
  154. {
  155. if (stat(name, &st))
  156. {
  157. error(ERROR_system(0), "%s: cannot stat", name);
  158. break;
  159. }
  160. if ((st.st_mode & (S_ISVTX|S_ISUID|S_ISGID)) != (mode & (S_ISVTX|S_ISUID|S_ISGID)) && chmod(name, mode))
  161. {
  162. error(ERROR_system(0), "%s: cannot change mode from %s to %s", name, fmtperm(st.st_mode & (S_ISVTX|S_ISUID|S_ISGID)), fmtperm(mode));
  163. break;
  164. }
  165. }
  166. }
  167. }
  168. else if (vflag)
  169. error(0, "%s: directory created", arg);
  170. }
  171. if (mask)
  172. umask(mask);
  173. return error_info.errors != 0;
  174. }