unmount.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. unmount.c
  9. Abstract:
  10. This module implements the unmount program.
  11. Author:
  12. Chris Stevens 30-Jul-2013
  13. Environment:
  14. User
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/lib/minocaos.h>
  20. #include <minoca/lib/mlibc.h>
  21. #include <assert.h>
  22. #include <errno.h>
  23. #include <getopt.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <unistd.h>
  28. //
  29. // ---------------------------------------------------------------- Definitions
  30. //
  31. #define UNMOUNT_VERSION_MAJOR 1
  32. #define UNMOUNT_VERSION_MINOR 0
  33. #define UNMOUNT_USAGE \
  34. "usage: umount [-Rl] mount_point\n\n" \
  35. "Options:\n" \
  36. " -l --lazy -- Lazily unmount the device from the directory, preventing\n"\
  37. " new accesses, but don't clean up until all references are" \
  38. " dropped.\n" \
  39. " -R --recursive -- Recursively unmount the specified mount point.\n" \
  40. " --help -- Display this help text.\n"
  41. #define UNMOUNT_OPTIONS_STRING "lR"
  42. //
  43. // ------------------------------------------------------ Data Type Definitions
  44. //
  45. //
  46. // ----------------------------------------------- Internal Function Prototypes
  47. //
  48. INT
  49. Unmount (
  50. PSTR MountPointPath,
  51. ULONG Flags
  52. );
  53. //
  54. // -------------------------------------------------------------------- Globals
  55. //
  56. struct option UnmountLongOptions[] = {
  57. {"lazy", no_argument, 0, 'l'},
  58. {"recursive", no_argument, 0, 'R'},
  59. {"help", no_argument, 0, 'h'},
  60. {"version", no_argument, 0, 'V'},
  61. {NULL, 0, 0, 0}
  62. };
  63. //
  64. // ------------------------------------------------------------------ Functions
  65. //
  66. INT
  67. main (
  68. INT ArgumentCount,
  69. CHAR **Arguments
  70. )
  71. /*++
  72. Routine Description:
  73. This routine implements the unmount user mode program.
  74. Arguments:
  75. ArgumentCount - Supplies the number of elements in the arguments array.
  76. Arguments - Supplies an array of strings. The array count is bounded by the
  77. previous parameter, and the strings are null-terminated.
  78. Return Value:
  79. 0 on success.
  80. Non-zero on failure.
  81. --*/
  82. {
  83. ULONG ArgumentIndex;
  84. ULONG Flags;
  85. PSTR MountPointPath;
  86. INT Option;
  87. INT ReturnValue;
  88. BOOL UnmountAttempted;
  89. Flags = 0;
  90. ReturnValue = 0;
  91. MountPointPath = NULL;
  92. UnmountAttempted = FALSE;
  93. //
  94. // There should be no more than three arguments.
  95. //
  96. if (ArgumentCount > 3) {
  97. ReturnValue = EINVAL;
  98. goto mainEnd;
  99. }
  100. //
  101. // Process the control arguments.
  102. //
  103. while (TRUE) {
  104. Option = getopt_long(ArgumentCount,
  105. Arguments,
  106. UNMOUNT_OPTIONS_STRING,
  107. UnmountLongOptions,
  108. NULL);
  109. if (Option == -1) {
  110. break;
  111. }
  112. if ((Option == '?') || (Option == ':')) {
  113. ReturnValue = 1;
  114. goto mainEnd;
  115. }
  116. switch (Option) {
  117. case 'l':
  118. Flags |= SYS_MOUNT_FLAG_DETACH;
  119. break;
  120. case 'R':
  121. Flags |= SYS_MOUNT_FLAG_RECURSIVE;
  122. break;
  123. case 'V':
  124. printf("unmount version %d.%02d\n",
  125. UNMOUNT_VERSION_MAJOR,
  126. UNMOUNT_VERSION_MINOR);
  127. ReturnValue = 1;
  128. goto mainEnd;
  129. case 'h':
  130. printf(UNMOUNT_USAGE);
  131. return 1;
  132. default:
  133. assert(FALSE);
  134. ReturnValue = 1;
  135. goto mainEnd;
  136. }
  137. }
  138. ArgumentIndex = optind;
  139. if (ArgumentIndex > ArgumentCount) {
  140. ArgumentIndex = ArgumentCount;
  141. }
  142. if (ArgumentIndex < ArgumentCount) {
  143. MountPointPath = Arguments[ArgumentIndex];
  144. }
  145. //
  146. // There must be a target path.
  147. //
  148. if (MountPointPath == NULL) {
  149. ReturnValue = EINVAL;
  150. goto mainEnd;
  151. }
  152. //
  153. // Attempt the unmount.
  154. //
  155. ReturnValue = Unmount(MountPointPath, Flags);
  156. UnmountAttempted = TRUE;
  157. mainEnd:
  158. if ((ReturnValue == EINVAL) && (UnmountAttempted == FALSE)) {
  159. printf(UNMOUNT_USAGE);
  160. }
  161. return ReturnValue;
  162. }
  163. //
  164. // --------------------------------------------------------- Internal Functions
  165. //
  166. INT
  167. Unmount (
  168. PSTR MountPointPath,
  169. ULONG Flags
  170. )
  171. /*++
  172. Routine Description:
  173. This routine unmounts the given directory.
  174. Arguments:
  175. MountPointPath - Supplies a pointer to the mount point path to be unmounted.
  176. Flags - Supplies the flags to send with the unmount command.
  177. See SYS_MOUNT_FLAG_* definitions.
  178. Return Value:
  179. 0 on success.
  180. Non-zero on failure.
  181. --*/
  182. {
  183. INT ReturnValue;
  184. KSTATUS Status;
  185. ReturnValue = 0;
  186. Status = OsUnmount(MountPointPath,
  187. RtlStringLength(MountPointPath) + 1,
  188. Flags);
  189. if (!KSUCCESS(Status)) {
  190. ReturnValue = ClConvertKstatusToErrorNumber(Status);
  191. fprintf(stderr,
  192. "Error: failed to unmount %s with error %d: %s.\n",
  193. MountPointPath,
  194. Status,
  195. strerror(ReturnValue));
  196. }
  197. return ReturnValue;
  198. }