PageRenderTime 40ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/hadoop-common-project/hadoop-common/src/main/winutils/chown.c

http://github.com/apache/hadoop-common
C | 270 lines | 173 code | 32 blank | 65 comment | 55 complexity | fa5e823254571d89b238b994d9284cb0 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with this
  4. * work for additional information regarding copyright ownership. The ASF
  5. * licenses this file to you under the Apache License, Version 2.0 (the
  6. * "License"); you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. * License for the specific language governing permissions and limitations under
  15. * the License.
  16. */
  17. #include "winutils.h"
  18. //----------------------------------------------------------------------------
  19. // Function: ChangeFileOwnerBySid
  20. //
  21. // Description:
  22. // Change a file or directory ownership by giving new owner and group SIDs
  23. //
  24. // Returns:
  25. // ERROR_SUCCESS: on success
  26. // Error code: otherwise
  27. //
  28. // Notes:
  29. // This function is long path safe, i.e. the path will be converted to long
  30. // path format if not already converted. So the caller does not need to do
  31. // the converstion before calling the method.
  32. //
  33. static DWORD ChangeFileOwnerBySid(__in LPCWSTR path,
  34. __in_opt PSID pNewOwnerSid, __in_opt PSID pNewGroupSid)
  35. {
  36. LPWSTR longPathName = NULL;
  37. INT oldMode = 0;
  38. SECURITY_INFORMATION securityInformation = 0;
  39. DWORD dwRtnCode = ERROR_SUCCESS;
  40. // Convert the path the the long path
  41. //
  42. dwRtnCode = ConvertToLongPath(path, &longPathName);
  43. if (dwRtnCode != ERROR_SUCCESS)
  44. {
  45. goto ChangeFileOwnerByNameEnd;
  46. }
  47. // Get a pointer to the existing owner information and DACL
  48. //
  49. dwRtnCode = FindFileOwnerAndPermission(longPathName, FALSE, NULL, NULL, &oldMode);
  50. if (dwRtnCode != ERROR_SUCCESS)
  51. {
  52. goto ChangeFileOwnerByNameEnd;
  53. }
  54. // We need SeTakeOwnershipPrivilege to set the owner if the caller does not
  55. // have WRITE_OWNER access to the object; we need SeRestorePrivilege if the
  56. // SID is not contained in the caller's token, and have the SE_GROUP_OWNER
  57. // permission enabled.
  58. //
  59. if (!EnablePrivilege(L"SeTakeOwnershipPrivilege"))
  60. {
  61. fwprintf(stdout, L"INFO: The user does not have SeTakeOwnershipPrivilege.\n");
  62. }
  63. if (!EnablePrivilege(L"SeRestorePrivilege"))
  64. {
  65. fwprintf(stdout, L"INFO: The user does not have SeRestorePrivilege.\n");
  66. }
  67. assert(pNewOwnerSid != NULL || pNewGroupSid != NULL);
  68. // Set the owners of the file.
  69. //
  70. if (pNewOwnerSid != NULL) securityInformation |= OWNER_SECURITY_INFORMATION;
  71. if (pNewGroupSid != NULL) securityInformation |= GROUP_SECURITY_INFORMATION;
  72. dwRtnCode = SetNamedSecurityInfoW(
  73. longPathName,
  74. SE_FILE_OBJECT,
  75. securityInformation,
  76. pNewOwnerSid,
  77. pNewGroupSid,
  78. NULL,
  79. NULL);
  80. if (dwRtnCode != ERROR_SUCCESS)
  81. {
  82. goto ChangeFileOwnerByNameEnd;
  83. }
  84. // Set the permission on the file for the new owner.
  85. //
  86. dwRtnCode = ChangeFileModeByMask(longPathName, oldMode);
  87. if (dwRtnCode != ERROR_SUCCESS)
  88. {
  89. goto ChangeFileOwnerByNameEnd;
  90. }
  91. ChangeFileOwnerByNameEnd:
  92. LocalFree(longPathName);
  93. return dwRtnCode;
  94. }
  95. //----------------------------------------------------------------------------
  96. // Function: Chown
  97. //
  98. // Description:
  99. // The main method for chown command
  100. //
  101. // Returns:
  102. // 0: on success
  103. //
  104. // Notes:
  105. //
  106. //
  107. int Chown(__in int argc, __in_ecount(argc) wchar_t *argv[])
  108. {
  109. LPWSTR pathName = NULL;
  110. LPWSTR ownerInfo = NULL;
  111. WCHAR const * colonPos = NULL;
  112. LPWSTR userName = NULL;
  113. size_t userNameLen = 0;
  114. LPWSTR groupName = NULL;
  115. size_t groupNameLen = 0;
  116. PSID pNewOwnerSid = NULL;
  117. PSID pNewGroupSid = NULL;
  118. DWORD dwRtnCode = 0;
  119. int ret = EXIT_FAILURE;
  120. if (argc >= 3)
  121. {
  122. ownerInfo = argv[1];
  123. pathName = argv[2];
  124. }
  125. else
  126. {
  127. fwprintf(stderr, L"Incorrect command line arguments.\n\n");
  128. ChownUsage(argv[0]);
  129. return ret;
  130. }
  131. // Parsing the owner name
  132. //
  133. if ((colonPos = wcschr(ownerInfo, L':')) != NULL)
  134. {
  135. if (colonPos - ownerInfo != 0)
  136. {
  137. // Length includes NULL terminator
  138. userNameLen = colonPos - ownerInfo + 1;
  139. userName = (LPTSTR)LocalAlloc(LPTR, userNameLen * sizeof(WCHAR));
  140. if (userName == NULL)
  141. {
  142. ReportErrorCode(L"LocalAlloc", GetLastError());
  143. goto ChownEnd;
  144. }
  145. if (FAILED(StringCchCopyNW(userName, userNameLen,
  146. ownerInfo, userNameLen - 1)))
  147. goto ChownEnd;
  148. }
  149. if (*(colonPos + 1) != 0)
  150. {
  151. // Length includes NULL terminator
  152. groupNameLen = wcslen(ownerInfo) - (colonPos - ownerInfo) + 1;
  153. groupName = (LPTSTR)LocalAlloc(LPTR, groupNameLen * sizeof(WCHAR));
  154. if (groupName == NULL)
  155. {
  156. ReportErrorCode(L"LocalAlloc", GetLastError());
  157. goto ChownEnd;
  158. }
  159. if (FAILED(StringCchCopyNW(groupName, groupNameLen,
  160. colonPos + 1, groupNameLen)))
  161. goto ChownEnd;
  162. }
  163. }
  164. else
  165. {
  166. // Length includes NULL terminator
  167. userNameLen = wcslen(ownerInfo) + 1;
  168. userName = (LPWSTR)LocalAlloc(LPTR, userNameLen * sizeof(WCHAR));
  169. if (userName == NULL)
  170. {
  171. ReportErrorCode(L"LocalAlloc", GetLastError());
  172. goto ChownEnd;
  173. }
  174. if (FAILED(StringCchCopyNW(userName, userNameLen, ownerInfo, userNameLen)))
  175. goto ChownEnd;
  176. }
  177. // Not allow zero length user name or group name in the parsing results.
  178. //
  179. assert(userName == NULL || wcslen(userName) > 0);
  180. assert(groupName == NULL || wcslen(groupName) > 0);
  181. // Nothing to change if both names are empty
  182. //
  183. if ((userName == NULL) && (groupName == NULL))
  184. {
  185. ret = EXIT_SUCCESS;
  186. goto ChownEnd;
  187. }
  188. if (userName != NULL)
  189. {
  190. dwRtnCode = GetSidFromAcctNameW(userName, &pNewOwnerSid);
  191. if (dwRtnCode != ERROR_SUCCESS)
  192. {
  193. ReportErrorCode(L"GetSidFromAcctName", dwRtnCode);
  194. fwprintf(stderr, L"Invalid user name: %s\n", userName);
  195. goto ChownEnd;
  196. }
  197. }
  198. if (groupName != NULL)
  199. {
  200. dwRtnCode = GetSidFromAcctNameW(groupName, &pNewGroupSid);
  201. if (dwRtnCode != ERROR_SUCCESS)
  202. {
  203. ReportErrorCode(L"GetSidFromAcctName", dwRtnCode);
  204. fwprintf(stderr, L"Invalid group name: %s\n", groupName);
  205. goto ChownEnd;
  206. }
  207. }
  208. if (wcslen(pathName) == 0 || wcsspn(pathName, L"/?|><:*\"") != 0)
  209. {
  210. fwprintf(stderr, L"Incorrect file name format: %s\n", pathName);
  211. goto ChownEnd;
  212. }
  213. dwRtnCode = ChangeFileOwnerBySid(pathName, pNewOwnerSid, pNewGroupSid);
  214. if (dwRtnCode != ERROR_SUCCESS)
  215. {
  216. ReportErrorCode(L"ChangeFileOwnerBySid", dwRtnCode);
  217. goto ChownEnd;
  218. }
  219. ret = EXIT_SUCCESS;
  220. ChownEnd:
  221. LocalFree(userName);
  222. LocalFree(groupName);
  223. LocalFree(pNewOwnerSid);
  224. LocalFree(pNewGroupSid);
  225. return ret;
  226. }
  227. void ChownUsage(LPCWSTR program)
  228. {
  229. fwprintf(stdout, L"\
  230. Usage: %s [OWNER][:[GROUP]] [FILE]\n\
  231. Change the owner and/or group of the FILE to OWNER and/or GROUP.\n\
  232. \n\
  233. Note:\n\
  234. On Linux, if a colon but no group name follows the user name, the group of\n\
  235. the files is changed to that user\'s login group. Windows has no concept of\n\
  236. a user's login group. So we do not change the group owner in this case.\n",
  237. program);
  238. }