symlink.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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: Symlink
  20. //
  21. // Description:
  22. // The main method for symlink command
  23. //
  24. // Returns:
  25. // 0: on success
  26. //
  27. // Notes:
  28. //
  29. int Symlink(__in int argc, __in_ecount(argc) wchar_t *argv[])
  30. {
  31. PWSTR longLinkName = NULL;
  32. PWSTR longFileName = NULL;
  33. DWORD dwErrorCode = ERROR_SUCCESS;
  34. BOOL isDir = FALSE;
  35. DWORD dwRtnCode = ERROR_SUCCESS;
  36. DWORD dwFlag = 0;
  37. int ret = SUCCESS;
  38. if (argc != 3)
  39. {
  40. SymlinkUsage();
  41. return FAILURE;
  42. }
  43. dwErrorCode = ConvertToLongPath(argv[1], &longLinkName);
  44. if (dwErrorCode != ERROR_SUCCESS)
  45. {
  46. ret = FAILURE;
  47. goto SymlinkEnd;
  48. }
  49. dwErrorCode = ConvertToLongPath(argv[2], &longFileName);
  50. if (dwErrorCode != ERROR_SUCCESS)
  51. {
  52. ret = FAILURE;
  53. goto SymlinkEnd;
  54. }
  55. // Check if the the process's access token has the privilege to create
  56. // symbolic links. Without this step, the call to CreateSymbolicLink() from
  57. // users have the privilege to create symbolic links will still succeed.
  58. // This is just an additional step to do the privilege check by not using
  59. // error code from CreateSymbolicLink() method.
  60. //
  61. if (!EnablePrivilege(L"SeCreateSymbolicLinkPrivilege"))
  62. {
  63. fwprintf(stderr,
  64. L"No privilege to create symbolic links.\n");
  65. ret = SYMLINK_NO_PRIVILEGE;
  66. goto SymlinkEnd;
  67. }
  68. if ((dwRtnCode = DirectoryCheck(longFileName, &isDir)) != ERROR_SUCCESS)
  69. {
  70. ReportErrorCode(L"DirectoryCheck", dwRtnCode);
  71. ret = FAILURE;
  72. goto SymlinkEnd;
  73. }
  74. if (isDir)
  75. dwFlag = SYMBOLIC_LINK_FLAG_DIRECTORY;
  76. if (!CreateSymbolicLinkW(longLinkName, longFileName, dwFlag))
  77. {
  78. ReportErrorCode(L"CreateSymbolicLink", GetLastError());
  79. ret = FAILURE;
  80. goto SymlinkEnd;
  81. }
  82. SymlinkEnd:
  83. LocalFree(longLinkName);
  84. LocalFree(longFileName);
  85. return ret;
  86. }
  87. void SymlinkUsage()
  88. {
  89. fwprintf(stdout, L"\
  90. Usage: symlink [LINKNAME] [FILENAME]\n\
  91. Creates a symbolic link\n\
  92. \n\
  93. 0 is returned on success.\n\
  94. 2 is returned if the user does no have privilege to create symbolic links.\n\
  95. 1 is returned for all other errors.\n\
  96. \n\
  97. The default security settings in Windows disallow non-elevated administrators\n\
  98. and all non-administrators from creating symbolic links. The security settings\n\
  99. for symbolic links can be changed in the Local Security Policy management\n\
  100. console.\n");
  101. }