You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by su...@apache.org on 2013/03/06 20:15:22 UTC
svn commit: r1453486 [4/7] - in
/hadoop/common/trunk/hadoop-common-project/hadoop-common: ./ src/main/bin/
src/main/conf/ src/main/docs/src/documentation/content/xdocs/
src/main/java/ src/main/java/org/apache/hadoop/fs/
src/main/java/org/apache/hadoop/...
Added: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/chmod.c
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/chmod.c?rev=1453486&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/chmod.c (added)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/chmod.c Wed Mar 6 19:15:18 2013
@@ -0,0 +1,893 @@
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with this
+* work for additional information regarding copyright ownership. The ASF
+* licenses this file to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations under
+* the License.
+*/
+
+#include "winutils.h"
+#include <errno.h>
+
+enum CHMOD_WHO
+{
+ CHMOD_WHO_NONE = 0,
+ CHMOD_WHO_OTHER = 07,
+ CHMOD_WHO_GROUP = 070,
+ CHMOD_WHO_USER = 0700,
+ CHMOD_WHO_ALL = CHMOD_WHO_OTHER | CHMOD_WHO_GROUP | CHMOD_WHO_USER
+};
+
+enum CHMOD_OP
+{
+ CHMOD_OP_INVALID,
+ CHMOD_OP_PLUS,
+ CHMOD_OP_MINUS,
+ CHMOD_OP_EQUAL,
+};
+
+enum CHMOD_PERM
+{
+ CHMOD_PERM_NA = 00,
+ CHMOD_PERM_R = 01,
+ CHMOD_PERM_W = 02,
+ CHMOD_PERM_X = 04,
+ CHMOD_PERM_LX = 010,
+};
+
+/*
+ * We use the following struct to build a linked list of mode change actions.
+ * The mode is described by the following grammar:
+ * mode ::= clause [, clause ...]
+ * clause ::= [who ...] [action ...]
+ * action ::= op [perm ...] | op [ref]
+ * who ::= a | u | g | o
+ * op ::= + | - | =
+ * perm ::= r | w | x | X
+ * ref ::= u | g | o
+ */
+typedef struct _MODE_CHANGE_ACTION
+{
+ USHORT who;
+ USHORT op;
+ USHORT perm;
+ USHORT ref;
+ struct _MODE_CHANGE_ACTION *next_action;
+} MODE_CHANGE_ACTION, *PMODE_CHANGE_ACTION;
+
+const MODE_CHANGE_ACTION INIT_MODE_CHANGE_ACTION = {
+ CHMOD_WHO_NONE, CHMOD_OP_INVALID, CHMOD_PERM_NA, CHMOD_WHO_NONE, NULL
+};
+
+static BOOL ParseOctalMode(LPCWSTR tsMask, INT *uMask);
+
+static BOOL ParseMode(LPCWSTR modeString, PMODE_CHANGE_ACTION *actions);
+
+static BOOL FreeActions(PMODE_CHANGE_ACTION actions);
+
+static BOOL ParseCommandLineArguments(__in int argc, __in wchar_t *argv[],
+ __out BOOL *rec, __out_opt INT *mask,
+ __out_opt PMODE_CHANGE_ACTION *actions, __out LPCWSTR *path);
+
+static BOOL ChangeFileModeByActions(__in LPCWSTR path,
+ PMODE_CHANGE_ACTION actions);
+
+static BOOL ChangeFileMode(__in LPCWSTR path, __in_opt INT mode,
+ __in_opt PMODE_CHANGE_ACTION actions);
+
+static BOOL ChangeFileModeRecursively(__in LPCWSTR path, __in_opt INT mode,
+ __in_opt PMODE_CHANGE_ACTION actions);
+
+
+//----------------------------------------------------------------------------
+// Function: Chmod
+//
+// Description:
+// The main method for chmod command
+//
+// Returns:
+// 0: on success
+//
+// Notes:
+//
+int Chmod(int argc, wchar_t *argv[])
+{
+ LPWSTR pathName = NULL;
+ LPWSTR longPathName = NULL;
+
+ BOOL recursive = FALSE;
+
+ PMODE_CHANGE_ACTION actions = NULL;
+
+ INT unixAccessMask = 0;
+
+ DWORD dwRtnCode = 0;
+
+ int ret = EXIT_FAILURE;
+
+ // Parsing chmod arguments
+ //
+ if (!ParseCommandLineArguments(argc, argv,
+ &recursive, &unixAccessMask, &actions, &pathName))
+ {
+ fwprintf(stderr, L"Incorrect command line arguments.\n\n");
+ ChmodUsage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ // Convert the path the the long path
+ //
+ dwRtnCode = ConvertToLongPath(pathName, &longPathName);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"ConvertToLongPath", dwRtnCode);
+ goto ChmodEnd;
+ }
+
+ if (!recursive)
+ {
+ if (ChangeFileMode(longPathName, unixAccessMask, actions))
+ {
+ ret = EXIT_SUCCESS;
+ }
+ }
+ else
+ {
+ if (ChangeFileModeRecursively(longPathName, unixAccessMask, actions))
+ {
+ ret = EXIT_SUCCESS;
+ }
+ }
+
+ChmodEnd:
+ FreeActions(actions);
+ LocalFree(longPathName);
+
+ return ret;
+}
+
+//----------------------------------------------------------------------------
+// Function: ChangeFileMode
+//
+// Description:
+// Wrapper function for change file mode. Choose either change by action or by
+// access mask.
+//
+// Returns:
+// TRUE: on success
+// FALSE: otherwise
+//
+// Notes:
+//
+static BOOL ChangeFileMode(__in LPCWSTR path, __in_opt INT unixAccessMask,
+ __in_opt PMODE_CHANGE_ACTION actions)
+{
+ if (actions != NULL)
+ return ChangeFileModeByActions(path, actions);
+ else
+ {
+ DWORD dwRtnCode = ChangeFileModeByMask(path, unixAccessMask);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"ChangeFileModeByMask", dwRtnCode);
+ return FALSE;
+ }
+ return TRUE;
+ }
+}
+
+//----------------------------------------------------------------------------
+// Function: ChangeFileModeRecursively
+//
+// Description:
+// Travel the directory recursively to change the permissions.
+//
+// Returns:
+// TRUE: on success
+// FALSE: otherwise
+//
+// Notes:
+// The recursion works in the following way:
+// - If the path is not a directory, change its mode and return.
+// Symbolic links and junction points are not considered as directories.
+// - Otherwise, call the method on all its children, then change its mode.
+//
+static BOOL ChangeFileModeRecursively(__in LPCWSTR path, __in_opt INT mode,
+ __in_opt PMODE_CHANGE_ACTION actions)
+{
+ BOOL isDir = FALSE;
+ BOOL isSymlink = FALSE;
+ LPWSTR dir = NULL;
+
+ size_t pathSize = 0;
+ size_t dirSize = 0;
+
+ HANDLE hFind = INVALID_HANDLE_VALUE;
+ WIN32_FIND_DATA ffd;
+ DWORD dwRtnCode = ERROR_SUCCESS;
+ BOOL ret = FALSE;
+
+ if ((dwRtnCode = DirectoryCheck(path, &isDir)) != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"IsDirectory", dwRtnCode);
+ return FALSE;
+ }
+ if ((dwRtnCode = SymbolicLinkCheck(path, &isSymlink)) != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"IsSymbolicLink", dwRtnCode);
+ return FALSE;
+ }
+
+ if (isSymlink || !isDir)
+ {
+ if (ChangeFileMode(path, mode, actions))
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ if (FAILED(StringCchLengthW(path, STRSAFE_MAX_CCH - 3, &pathSize)))
+ {
+ return FALSE;
+ }
+ dirSize = pathSize + 3;
+ dir = (LPWSTR)LocalAlloc(LPTR, dirSize * sizeof(WCHAR));
+ if (dir == NULL)
+ {
+ ReportErrorCode(L"LocalAlloc", GetLastError());
+ goto ChangeFileModeRecursivelyEnd;
+ }
+
+ if (FAILED(StringCchCopyW(dir, dirSize, path)) ||
+ FAILED(StringCchCatW(dir, dirSize, L"\\*")))
+ {
+ goto ChangeFileModeRecursivelyEnd;
+ }
+
+ hFind = FindFirstFile(dir, &ffd);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ ReportErrorCode(L"FindFirstFile", GetLastError());
+ goto ChangeFileModeRecursivelyEnd;
+ }
+
+ do
+ {
+ LPWSTR filename = NULL;
+ LPWSTR longFilename = NULL;
+ size_t filenameSize = 0;
+
+ if (wcscmp(ffd.cFileName, L".") == 0 ||
+ wcscmp(ffd.cFileName, L"..") == 0)
+ continue;
+
+ filenameSize = pathSize + wcslen(ffd.cFileName) + 2;
+ filename = (LPWSTR)LocalAlloc(LPTR, filenameSize * sizeof(WCHAR));
+ if (filename == NULL)
+ {
+ ReportErrorCode(L"LocalAlloc", GetLastError());
+ goto ChangeFileModeRecursivelyEnd;
+ }
+
+ if (FAILED(StringCchCopyW(filename, filenameSize, path)) ||
+ FAILED(StringCchCatW(filename, filenameSize, L"\\")) ||
+ FAILED(StringCchCatW(filename, filenameSize, ffd.cFileName)))
+ {
+ LocalFree(filename);
+ goto ChangeFileModeRecursivelyEnd;
+ }
+
+ // The child fileanme is not prepended with long path prefix.
+ // Convert the filename to long path format.
+ //
+ dwRtnCode = ConvertToLongPath(filename, &longFilename);
+ LocalFree(filename);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"ConvertToLongPath", dwRtnCode);
+ LocalFree(longFilename);
+ goto ChangeFileModeRecursivelyEnd;
+ }
+
+ if(!ChangeFileModeRecursively(longFilename, mode, actions))
+ {
+ LocalFree(longFilename);
+ goto ChangeFileModeRecursivelyEnd;
+ }
+
+ LocalFree(longFilename);
+
+ } while (FindNextFileW(hFind, &ffd));
+
+ if (!ChangeFileMode(path, mode, actions))
+ {
+ goto ChangeFileModeRecursivelyEnd;
+ }
+
+ ret = TRUE;
+
+ChangeFileModeRecursivelyEnd:
+ LocalFree(dir);
+
+ return ret;
+}
+
+//----------------------------------------------------------------------------
+// Function: ParseCommandLineArguments
+//
+// Description:
+// Parse command line arguments for chmod.
+//
+// Returns:
+// TRUE: on success
+// FALSE: otherwise
+//
+// Notes:
+// 1. Recursive is only set on directories
+// 2. 'actions' is NULL if the mode is octal
+//
+static BOOL ParseCommandLineArguments(__in int argc, __in wchar_t *argv[],
+ __out BOOL *rec,
+ __out_opt INT *mask,
+ __out_opt PMODE_CHANGE_ACTION *actions,
+ __out LPCWSTR *path)
+{
+ LPCWSTR maskString;
+ BY_HANDLE_FILE_INFORMATION fileInfo;
+ DWORD dwRtnCode = ERROR_SUCCESS;
+
+ assert(path != NULL);
+
+ if (argc != 3 && argc != 4)
+ return FALSE;
+
+ *rec = FALSE;
+ if (argc == 4)
+ {
+ maskString = argv[2];
+ *path = argv[3];
+
+ if (wcscmp(argv[1], L"-R") == 0)
+ {
+ // Check if the given path name is a file or directory
+ // Only set recursive flag if the given path is a directory
+ //
+ dwRtnCode = GetFileInformationByName(*path, FALSE, &fileInfo);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"GetFileInformationByName", dwRtnCode);
+ return FALSE;
+ }
+
+ if (IsDirFileInfo(&fileInfo))
+ {
+ *rec = TRUE;
+ }
+ }
+ else
+ return FALSE;
+ }
+ else
+ {
+ maskString = argv[1];
+ *path = argv[2];
+ }
+
+ if (ParseOctalMode(maskString, mask))
+ {
+ return TRUE;
+ }
+ else if (ParseMode(maskString, actions))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//----------------------------------------------------------------------------
+// Function: FreeActions
+//
+// Description:
+// Free a linked list of mode change actions given the head node.
+//
+// Returns:
+// TRUE: on success
+// FALSE: otherwise
+//
+// Notes:
+// none
+//
+static BOOL FreeActions(PMODE_CHANGE_ACTION actions)
+{
+ PMODE_CHANGE_ACTION curr = NULL;
+ PMODE_CHANGE_ACTION next = NULL;
+
+ // Nothing to free if NULL is passed in
+ //
+ if (actions == NULL)
+ {
+ return TRUE;
+ }
+
+ curr = actions;
+ while (curr != NULL)
+ {
+ next = curr->next_action;
+ LocalFree(curr);
+ curr = next;
+ }
+ actions = NULL;
+
+ return TRUE;
+}
+
+//----------------------------------------------------------------------------
+// Function: ComputeNewMode
+//
+// Description:
+// Compute a new mode based on the old mode and a mode change action.
+//
+// Returns:
+// The newly computed mode
+//
+// Notes:
+// Apply 'rwx' permission mask or reference permission mode according to the
+// '+', '-', or '=' operator.
+//
+static INT ComputeNewMode(__in INT oldMode,
+ __in USHORT who, __in USHORT op,
+ __in USHORT perm, __in USHORT ref)
+{
+ static const INT readMask = 0444;
+ static const INT writeMask = 0222;
+ static const INT exeMask = 0111;
+
+ INT mask = 0;
+ INT mode = 0;
+
+ // Operations are exclusive, and cannot be invalid
+ //
+ assert(op == CHMOD_OP_EQUAL || op == CHMOD_OP_PLUS || op == CHMOD_OP_MINUS);
+
+ // Nothing needs to be changed if there is not permission or reference
+ //
+ if(perm == CHMOD_PERM_NA && ref == CHMOD_WHO_NONE)
+ {
+ return oldMode;
+ }
+
+ // We should have only permissions or a reference target, not both.
+ //
+ assert((perm != CHMOD_PERM_NA && ref == CHMOD_WHO_NONE) ||
+ (perm == CHMOD_PERM_NA && ref != CHMOD_WHO_NONE));
+
+ if (perm != CHMOD_PERM_NA)
+ {
+ if ((perm & CHMOD_PERM_R) == CHMOD_PERM_R)
+ mask |= readMask;
+ if ((perm & CHMOD_PERM_W) == CHMOD_PERM_W)
+ mask |= writeMask;
+ if ((perm & CHMOD_PERM_X) == CHMOD_PERM_X)
+ mask |= exeMask;
+ if (((perm & CHMOD_PERM_LX) == CHMOD_PERM_LX))
+ {
+ // It applies execute permissions to directories regardless of their
+ // current permissions and applies execute permissions to a file which
+ // already has at least 1 execute permission bit already set (either user,
+ // group or other). It is only really useful when used with '+' and
+ // usually in combination with the -R option for giving group or other
+ // access to a big directory tree without setting execute permission on
+ // normal files (such as text files), which would normally happen if you
+ // just used "chmod -R a+rx .", whereas with 'X' you can do
+ // "chmod -R a+rX ." instead (Source: Wikipedia)
+ //
+ if ((oldMode & UX_DIRECTORY) == UX_DIRECTORY || (oldMode & exeMask))
+ mask |= exeMask;
+ }
+ }
+ else if (ref != CHMOD_WHO_NONE)
+ {
+ mask |= oldMode & ref;
+ switch(ref)
+ {
+ case CHMOD_WHO_GROUP:
+ mask |= mask >> 3;
+ mask |= mask << 3;
+ break;
+ case CHMOD_WHO_OTHER:
+ mask |= mask << 3;
+ mask |= mask << 6;
+ break;
+ case CHMOD_WHO_USER:
+ mask |= mask >> 3;
+ mask |= mask >> 6;
+ break;
+ default:
+ // Reference modes can only be U/G/O and are exclusive
+ assert(FALSE);
+ }
+ }
+
+ mask &= who;
+
+ if (op == CHMOD_OP_EQUAL)
+ {
+ mode = (oldMode & (~who)) | mask;
+ }
+ else if (op == CHMOD_OP_MINUS)
+ {
+ mode = oldMode & (~mask);
+ }
+ else if (op == CHMOD_OP_PLUS)
+ {
+ mode = oldMode | mask;
+ }
+
+ return mode;
+}
+
+//----------------------------------------------------------------------------
+// Function: ConvertActionsToMask
+//
+// Description:
+// Convert a linked list of mode change actions to the Unix permission mask
+// given the head node.
+//
+// Returns:
+// TRUE: on success
+// FALSE: otherwise
+//
+// Notes:
+// none
+//
+static BOOL ConvertActionsToMask(__in LPCWSTR path,
+ __in PMODE_CHANGE_ACTION actions, __out PINT puMask)
+{
+ PMODE_CHANGE_ACTION curr = NULL;
+
+ BY_HANDLE_FILE_INFORMATION fileInformation;
+ DWORD dwErrorCode = ERROR_SUCCESS;
+
+ INT mode = 0;
+
+ dwErrorCode = GetFileInformationByName(path, FALSE, &fileInformation);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"GetFileInformationByName", dwErrorCode);
+ return FALSE;
+ }
+ if (IsDirFileInfo(&fileInformation))
+ {
+ mode |= UX_DIRECTORY;
+ }
+ dwErrorCode = FindFileOwnerAndPermission(path, NULL, NULL, &mode);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"FindFileOwnerAndPermission", dwErrorCode);
+ return FALSE;
+ }
+ *puMask = mode;
+
+ // Nothing to change if NULL is passed in
+ //
+ if (actions == NULL)
+ {
+ return TRUE;
+ }
+
+ for (curr = actions; curr != NULL; curr = curr->next_action)
+ {
+ mode = ComputeNewMode(mode, curr->who, curr->op, curr->perm, curr->ref);
+ }
+
+ *puMask = mode;
+ return TRUE;
+}
+
+//----------------------------------------------------------------------------
+// Function: ChangeFileModeByActions
+//
+// Description:
+// Change a file mode through a list of actions.
+//
+// Returns:
+// TRUE: on success
+// FALSE: otherwise
+//
+// Notes:
+// none
+//
+static BOOL ChangeFileModeByActions(__in LPCWSTR path,
+ PMODE_CHANGE_ACTION actions)
+{
+ INT mask = 0;
+
+ if (ConvertActionsToMask(path, actions, &mask))
+ {
+ DWORD dwRtnCode = ChangeFileModeByMask(path, mask);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"ChangeFileModeByMask", dwRtnCode);
+ return FALSE;
+ }
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+//----------------------------------------------------------------------------
+// Function: ParseMode
+//
+// Description:
+// Convert a mode string into a linked list of actions
+//
+// Returns:
+// TRUE: on success
+// FALSE: otherwise
+//
+// Notes:
+// Take a state machine approach to parse the mode. Each mode change action
+// will be a node in the output linked list. The state machine has five state,
+// and each will only transit to the next; the end state can transit back to
+// the first state, and thus form a circle. In each state, if we see a
+// a character not belongs to the state, we will move to next state. WHO, PERM,
+// and REF states are optional; OP and END states are required; and errors
+// will only be reported at the latter two states.
+//
+static BOOL ParseMode(LPCWSTR modeString, PMODE_CHANGE_ACTION *pActions)
+{
+ enum __PARSE_MODE_ACTION_STATE
+ {
+ PARSE_MODE_ACTION_WHO_STATE,
+ PARSE_MODE_ACTION_OP_STATE,
+ PARSE_MODE_ACTION_PERM_STATE,
+ PARSE_MODE_ACTION_REF_STATE,
+ PARSE_MODE_ACTION_END_STATE
+ } state = PARSE_MODE_ACTION_WHO_STATE;
+
+ MODE_CHANGE_ACTION action = INIT_MODE_CHANGE_ACTION;
+ PMODE_CHANGE_ACTION actionsEnd = NULL;
+ PMODE_CHANGE_ACTION actionsLast = NULL;
+ USHORT lastWho;
+ WCHAR c = 0;
+ size_t len = 0;
+ size_t i = 0;
+
+ assert(modeString != NULL && pActions != NULL);
+
+ if (FAILED(StringCchLengthW(modeString, STRSAFE_MAX_CCH, &len)))
+ {
+ return FALSE;
+ }
+
+ actionsEnd = *pActions;
+ while(i <= len)
+ {
+ c = modeString[i];
+ if (state == PARSE_MODE_ACTION_WHO_STATE)
+ {
+ switch (c)
+ {
+ case L'a':
+ action.who |= CHMOD_WHO_ALL;
+ i++;
+ break;
+ case L'u':
+ action.who |= CHMOD_WHO_USER;
+ i++;
+ break;
+ case L'g':
+ action.who |= CHMOD_WHO_GROUP;
+ i++;
+ break;
+ case L'o':
+ action.who |= CHMOD_WHO_OTHER;
+ i++;
+ break;
+ default:
+ state = PARSE_MODE_ACTION_OP_STATE;
+ } // WHO switch
+ }
+ else if (state == PARSE_MODE_ACTION_OP_STATE)
+ {
+ switch (c)
+ {
+ case L'+':
+ action.op = CHMOD_OP_PLUS;
+ break;
+ case L'-':
+ action.op = CHMOD_OP_MINUS;
+ break;
+ case L'=':
+ action.op = CHMOD_OP_EQUAL;
+ break;
+ default:
+ fwprintf(stderr, L"Invalid mode: '%s'\n", modeString);
+ FreeActions(*pActions);
+ return FALSE;
+ } // OP switch
+ i++;
+ state = PARSE_MODE_ACTION_PERM_STATE;
+ }
+ else if (state == PARSE_MODE_ACTION_PERM_STATE)
+ {
+ switch (c)
+ {
+ case L'r':
+ action.perm |= CHMOD_PERM_R;
+ i++;
+ break;
+ case L'w':
+ action.perm |= CHMOD_PERM_W;
+ i++;
+ break;
+ case L'x':
+ action.perm |= CHMOD_PERM_X;
+ i++;
+ break;
+ case L'X':
+ action.perm |= CHMOD_PERM_LX;
+ i++;
+ break;
+ default:
+ state = PARSE_MODE_ACTION_REF_STATE;
+ } // PERM switch
+ }
+ else if (state == PARSE_MODE_ACTION_REF_STATE)
+ {
+ switch (c)
+ {
+ case L'u':
+ action.ref = CHMOD_WHO_USER;
+ i++;
+ break;
+ case L'g':
+ action.ref = CHMOD_WHO_GROUP;
+ i++;
+ break;
+ case L'o':
+ action.ref = CHMOD_WHO_OTHER;
+ i++;
+ break;
+ default:
+ state = PARSE_MODE_ACTION_END_STATE;
+ } // REF switch
+ }
+ else if (state == PARSE_MODE_ACTION_END_STATE)
+ {
+ switch (c)
+ {
+ case NULL:
+ case L',':
+ i++;
+ case L'+':
+ case L'-':
+ case L'=':
+ state = PARSE_MODE_ACTION_WHO_STATE;
+
+ // Append the current action to the end of the linked list
+ //
+ assert(actionsEnd == NULL);
+ // Allocate memory
+ actionsEnd = (PMODE_CHANGE_ACTION) LocalAlloc(LPTR,
+ sizeof(MODE_CHANGE_ACTION));
+ if (actionsEnd == NULL)
+ {
+ ReportErrorCode(L"LocalAlloc", GetLastError());
+ FreeActions(*pActions);
+ return FALSE;
+ }
+ if (action.who == CHMOD_WHO_NONE) action.who = CHMOD_WHO_ALL;
+ // Copy the action to the new node
+ *actionsEnd = action;
+ // Append to the last node in the linked list
+ if (actionsLast != NULL) actionsLast->next_action = actionsEnd;
+ // pActions should point to the head of the linked list
+ if (*pActions == NULL) *pActions = actionsEnd;
+ // Update the two pointers to point to the last node and the tail
+ actionsLast = actionsEnd;
+ actionsEnd = actionsLast->next_action;
+
+ // Reset action
+ //
+ lastWho = action.who;
+ action = INIT_MODE_CHANGE_ACTION;
+ if (c != L',')
+ {
+ action.who = lastWho;
+ }
+
+ break;
+ default:
+ fwprintf(stderr, L"Invalid mode: '%s'\n", modeString);
+ FreeActions(*pActions);
+ return FALSE;
+ } // END switch
+ }
+ } // while
+ return TRUE;
+}
+
+//----------------------------------------------------------------------------
+// Function: ParseOctalMode
+//
+// Description:
+// Convert the 3 or 4 digits Unix mask string into the binary representation
+// of the Unix access mask, i.e. 9 bits each an indicator of the permission
+// of 'rwxrwxrwx', i.e. user's, group's, and owner's read, write, and
+// execute/search permissions.
+//
+// Returns:
+// TRUE: on success
+// FALSE: otherwise
+//
+// Notes:
+// none
+//
+static BOOL ParseOctalMode(LPCWSTR tsMask, INT *uMask)
+{
+ size_t tsMaskLen = 0;
+ DWORD i;
+ LONG l;
+ WCHAR *end;
+
+ if (uMask == NULL)
+ return FALSE;
+
+ if (FAILED(StringCchLengthW(tsMask, STRSAFE_MAX_CCH, &tsMaskLen)))
+ return FALSE;
+
+ if (tsMaskLen == 0 || tsMaskLen > 4)
+ {
+ return FALSE;
+ }
+
+ for (i = 0; i < tsMaskLen; i++)
+ {
+ if (!(tsMask[tsMaskLen - i - 1] >= L'0' &&
+ tsMask[tsMaskLen - i - 1] <= L'7'))
+ return FALSE;
+ }
+
+ errno = 0;
+ if (tsMaskLen == 4)
+ // Windows does not have any equivalent of setuid/setgid and sticky bit.
+ // So the first bit is omitted for the 4 digit octal mode case.
+ //
+ l = wcstol(tsMask + 1, &end, 8);
+ else
+ l = wcstol(tsMask, &end, 8);
+
+ if (errno || l > 0x0777 || l < 0 || *end != 0)
+ {
+ return FALSE;
+ }
+
+ *uMask = (INT) l;
+
+ return TRUE;
+}
+
+void ChmodUsage(LPCWSTR program)
+{
+ fwprintf(stdout, L"\
+Usage: %s [OPTION] OCTAL-MODE [FILE]\n\
+ or: %s [OPTION] MODE [FILE]\n\
+Change the mode of the FILE to MODE.\n\
+\n\
+ -R: change files and directories recursively\n\
+\n\
+Each MODE is of the form '[ugoa]*([-+=]([rwxX]*|[ugo]))+'.\n",
+program, program);
+}
Added: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/chown.c
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/chown.c?rev=1453486&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/chown.c (added)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/chown.c Wed Mar 6 19:15:18 2013
@@ -0,0 +1,270 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "winutils.h"
+
+//----------------------------------------------------------------------------
+// Function: ChangeFileOwnerBySid
+//
+// Description:
+// Change a file or directory ownership by giving new owner and group SIDs
+//
+// Returns:
+// ERROR_SUCCESS: on success
+// Error code: otherwise
+//
+// Notes:
+// This function is long path safe, i.e. the path will be converted to long
+// path format if not already converted. So the caller does not need to do
+// the converstion before calling the method.
+//
+static DWORD ChangeFileOwnerBySid(__in LPCWSTR path,
+ __in_opt PSID pNewOwnerSid, __in_opt PSID pNewGroupSid)
+{
+ LPWSTR longPathName = NULL;
+ INT oldMode = 0;
+
+ SECURITY_INFORMATION securityInformation = 0;
+
+ DWORD dwRtnCode = ERROR_SUCCESS;
+
+ // Convert the path the the long path
+ //
+ dwRtnCode = ConvertToLongPath(path, &longPathName);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ goto ChangeFileOwnerByNameEnd;
+ }
+
+ // Get a pointer to the existing owner information and DACL
+ //
+ dwRtnCode = FindFileOwnerAndPermission(longPathName, NULL, NULL, &oldMode);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ goto ChangeFileOwnerByNameEnd;
+ }
+
+ // We need SeTakeOwnershipPrivilege to set the owner if the caller does not
+ // have WRITE_OWNER access to the object; we need SeRestorePrivilege if the
+ // SID is not contained in the caller's token, and have the SE_GROUP_OWNER
+ // permission enabled.
+ //
+ if (!EnablePrivilege(L"SeTakeOwnershipPrivilege"))
+ {
+ fwprintf(stdout, L"INFO: The user does not have SeTakeOwnershipPrivilege.\n");
+ }
+ if (!EnablePrivilege(L"SeRestorePrivilege"))
+ {
+ fwprintf(stdout, L"INFO: The user does not have SeRestorePrivilege.\n");
+ }
+
+ assert(pNewOwnerSid != NULL || pNewGroupSid != NULL);
+
+ // Set the owners of the file.
+ //
+ if (pNewOwnerSid != NULL) securityInformation |= OWNER_SECURITY_INFORMATION;
+ if (pNewGroupSid != NULL) securityInformation |= GROUP_SECURITY_INFORMATION;
+ dwRtnCode = SetNamedSecurityInfoW(
+ longPathName,
+ SE_FILE_OBJECT,
+ securityInformation,
+ pNewOwnerSid,
+ pNewGroupSid,
+ NULL,
+ NULL);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ goto ChangeFileOwnerByNameEnd;
+ }
+
+ // Set the permission on the file for the new owner.
+ //
+ dwRtnCode = ChangeFileModeByMask(longPathName, oldMode);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ goto ChangeFileOwnerByNameEnd;
+ }
+
+ChangeFileOwnerByNameEnd:
+ LocalFree(longPathName);
+ return dwRtnCode;
+}
+
+//----------------------------------------------------------------------------
+// Function: Chown
+//
+// Description:
+// The main method for chown command
+//
+// Returns:
+// 0: on success
+//
+// Notes:
+//
+//
+int Chown(int argc, wchar_t *argv[])
+{
+ LPWSTR pathName = NULL;
+
+ LPWSTR ownerInfo = NULL;
+
+ LPWSTR colonPos = NULL;
+
+ LPWSTR userName = NULL;
+ size_t userNameLen = 0;
+
+ LPWSTR groupName = NULL;
+ size_t groupNameLen = 0;
+
+ PSID pNewOwnerSid = NULL;
+ PSID pNewGroupSid = NULL;
+
+ DWORD dwRtnCode = 0;
+
+ int ret = EXIT_FAILURE;
+
+ if (argc >= 3)
+ {
+ ownerInfo = argv[1];
+ pathName = argv[2];
+ }
+ else
+ {
+ fwprintf(stderr, L"Incorrect command line arguments.\n\n");
+ ChownUsage(argv[0]);
+ return ret;
+ }
+
+ // Parsing the owner name
+ //
+ if ((colonPos = wcschr(ownerInfo, L':')) != NULL)
+ {
+ if (colonPos - ownerInfo != 0)
+ {
+ // Length includes NULL terminator
+ userNameLen = colonPos - ownerInfo + 1;
+ userName = (LPTSTR)LocalAlloc(LPTR, userNameLen * sizeof(WCHAR));
+ if (userName == NULL)
+ {
+ ReportErrorCode(L"LocalAlloc", GetLastError());
+ goto ChownEnd;
+ }
+ if (FAILED(StringCchCopyNW(userName, userNameLen,
+ ownerInfo, userNameLen - 1)))
+ goto ChownEnd;
+ }
+
+ if (*(colonPos + 1) != 0)
+ {
+ // Length includes NULL terminator
+ groupNameLen = wcslen(ownerInfo) - (colonPos - ownerInfo) + 1;
+ groupName = (LPTSTR)LocalAlloc(LPTR, groupNameLen * sizeof(WCHAR));
+ if (groupName == NULL)
+ {
+ ReportErrorCode(L"LocalAlloc", GetLastError());
+ goto ChownEnd;
+ }
+ if (FAILED(StringCchCopyNW(groupName, groupNameLen,
+ colonPos + 1, groupNameLen)))
+ goto ChownEnd;
+ }
+ }
+ else
+ {
+ // Length includes NULL terminator
+ userNameLen = wcslen(ownerInfo) + 1;
+ userName = (LPWSTR)LocalAlloc(LPTR, userNameLen * sizeof(WCHAR));
+ if (userName == NULL)
+ {
+ ReportErrorCode(L"LocalAlloc", GetLastError());
+ goto ChownEnd;
+ }
+ if (FAILED(StringCchCopyNW(userName, userNameLen, ownerInfo, userNameLen)))
+ goto ChownEnd;
+ }
+
+ // Not allow zero length user name or group name in the parsing results.
+ //
+ assert(userName == NULL || wcslen(userName) > 0);
+ assert(groupName == NULL || wcslen(groupName) > 0);
+
+ // Nothing to change if both names are empty
+ //
+ if ((userName == NULL) && (groupName == NULL))
+ {
+ ret = EXIT_SUCCESS;
+ goto ChownEnd;
+ }
+
+ if (userName != NULL)
+ {
+ dwRtnCode = GetSidFromAcctNameW(userName, &pNewOwnerSid);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"GetSidFromAcctName", dwRtnCode);
+ fwprintf(stderr, L"Invalid user name: %s\n", userName);
+ goto ChownEnd;
+ }
+ }
+
+ if (groupName != NULL)
+ {
+ dwRtnCode = GetSidFromAcctNameW(groupName, &pNewGroupSid);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"GetSidFromAcctName", dwRtnCode);
+ fwprintf(stderr, L"Invalid group name: %s\n", groupName);
+ goto ChownEnd;
+ }
+ }
+
+ if (wcslen(pathName) == 0 || wcsspn(pathName, L"/?|><:*\"") != 0)
+ {
+ fwprintf(stderr, L"Incorrect file name format: %s\n", pathName);
+ goto ChownEnd;
+ }
+
+ dwRtnCode = ChangeFileOwnerBySid(pathName, pNewOwnerSid, pNewGroupSid);
+ if (dwRtnCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"ChangeFileOwnerBySid", dwRtnCode);
+ goto ChownEnd;
+ }
+
+ ret = EXIT_SUCCESS;
+
+ChownEnd:
+ LocalFree(userName);
+ LocalFree(groupName);
+ LocalFree(pNewOwnerSid);
+ LocalFree(pNewGroupSid);
+
+ return ret;
+}
+
+void ChownUsage(LPCWSTR program)
+{
+ fwprintf(stdout, L"\
+Usage: %s [OWNER][:[GROUP]] [FILE]\n\
+Change the owner and/or group of the FILE to OWNER and/or GROUP.\n\
+\n\
+Note:\n\
+On Linux, if a colon but no group name follows the user name, the group of\n\
+the files is changed to that user\'s login group. Windows has no concept of\n\
+a user's login group. So we do not change the group owner in this case.\n",
+program);
+}
Added: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/groups.c
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/groups.c?rev=1453486&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/groups.c (added)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/groups.c Wed Mar 6 19:15:18 2013
@@ -0,0 +1,217 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+#include "winutils.h"
+
+//----------------------------------------------------------------------------
+// Function: PrintGroups
+//
+// Description:
+// Print group names to the console standard output for the given user
+//
+// Returns:
+// TRUE: on success
+//
+// Notes:
+// This function could fail on first pass when we fail to find groups for
+// domain account; so we do not report Windows API errors in this function.
+// If formatOutput is true, pipe character is used as separator for groups
+// otherwise, space.
+//
+static BOOL PrintGroups(
+ LPLOCALGROUP_USERS_INFO_0 groups,
+ DWORD entries,
+ BOOL formatOutput)
+{
+ BOOL ret = TRUE;
+ LPLOCALGROUP_USERS_INFO_0 pTmpBuf = groups;
+ DWORD i;
+
+ for (i = 0; i < entries; i++)
+ {
+ if (pTmpBuf == NULL)
+ {
+ ret = FALSE;
+ break;
+ }
+
+ if (i != 0)
+ {
+ if (formatOutput)
+ {
+ wprintf(L"|");
+ }
+ else
+ {
+ wprintf(L" ");
+ }
+ }
+ wprintf(L"%s", pTmpBuf->lgrui0_name);
+
+ pTmpBuf++;
+ }
+
+ if (ret)
+ wprintf(L"\n");
+
+ return ret;
+}
+
+//----------------------------------------------------------------------------
+// Function: ParseCommandLine
+//
+// Description:
+// Parses the command line
+//
+// Returns:
+// TRUE on the valid command line, FALSE otherwise
+//
+static BOOL ParseCommandLine(
+ int argc, wchar_t *argv[], wchar_t **user, BOOL *formatOutput)
+{
+ *formatOutput = FALSE;
+
+ assert(argv != NULL);
+ assert(user != NULL);
+
+ if (argc == 1)
+ {
+ // implicitly use the current user
+ *user = NULL;
+ return TRUE;
+ }
+ else if (argc == 2)
+ {
+ // check if the second argument is formating
+ if (wcscmp(argv[1], L"-F") == 0)
+ {
+ *user = NULL;
+ *formatOutput = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ *user = argv[1];
+ return TRUE;
+ }
+ }
+ else if (argc == 3 && wcscmp(argv[1], L"-F") == 0)
+ {
+ // if 3 args, the second argument must be "-F"
+
+ *user = argv[2];
+ *formatOutput = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//----------------------------------------------------------------------------
+// Function: Groups
+//
+// Description:
+// The main method for groups command
+//
+// Returns:
+// 0: on success
+//
+// Notes:
+//
+//
+int Groups(int argc, wchar_t *argv[])
+{
+ LPWSTR input = NULL;
+
+ LPWSTR currentUser = NULL;
+ DWORD cchCurrentUser = 0;
+
+ LPLOCALGROUP_USERS_INFO_0 groups = NULL;
+ DWORD entries = 0;
+
+ DWORD dwRtnCode = ERROR_SUCCESS;
+
+ int ret = EXIT_SUCCESS;
+ BOOL formatOutput = FALSE;
+
+ if (!ParseCommandLine(argc, argv, &input, &formatOutput))
+ {
+ fwprintf(stderr, L"Incorrect command line arguments.\n\n");
+ GroupsUsage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ // if username was not specified on the command line, fallback to the
+ // current user
+ if (input == NULL)
+ {
+ GetUserNameW(currentUser, &cchCurrentUser);
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ currentUser = (LPWSTR) LocalAlloc(LPTR,
+ (cchCurrentUser + 1) * sizeof(wchar_t));
+ if (!currentUser)
+ {
+ ReportErrorCode(L"LocalAlloc", GetLastError());
+ ret = EXIT_FAILURE;
+ goto GroupsEnd;
+ }
+ if (GetUserNameW(currentUser, &cchCurrentUser))
+ input = currentUser;
+ else
+ {
+ ReportErrorCode(L"GetUserName", GetLastError());
+ ret = EXIT_FAILURE;
+ goto GroupsEnd;
+ }
+ }
+ else
+ {
+ ReportErrorCode(L"GetUserName", GetLastError());
+ ret = EXIT_FAILURE;
+ goto GroupsEnd;
+ }
+ }
+
+ if ((dwRtnCode = GetLocalGroupsForUser(input, &groups, &entries))
+ != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"GetLocalGroupsForUser", dwRtnCode);
+ ret = EXIT_FAILURE;
+ goto GroupsEnd;
+ }
+
+ if (!PrintGroups(groups, entries, formatOutput))
+ {
+ ret = EXIT_FAILURE;
+ }
+
+GroupsEnd:
+ LocalFree(currentUser);
+ if (groups != NULL) NetApiBufferFree(groups);
+ return ret;
+}
+
+void GroupsUsage(LPCWSTR program)
+{
+ fwprintf(stdout, L"\
+Usage: %s [OPTIONS] [USERNAME]\n\
+Print group information of the specified USERNAME \
+(the current user by default).\n\
+\n\
+OPTIONS: -F format the output by separating tokens with a pipe\n",
+program);
+}
Added: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/hardlink.c
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/hardlink.c?rev=1453486&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/hardlink.c (added)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/hardlink.c Wed Mar 6 19:15:18 2013
@@ -0,0 +1,230 @@
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with this
+* work for additional information regarding copyright ownership. The ASF
+* licenses this file to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations under
+* the License.
+*/
+
+#include "winutils.h"
+
+// List of different hardlink related command line options supported by
+// winutils.
+typedef enum HardLinkCommandOptionType
+{
+ HardLinkInvalid,
+ HardLinkCreate,
+ HardLinkStat
+} HardLinkCommandOption;
+
+//----------------------------------------------------------------------------
+// Function: ParseCommandLine
+//
+// Description:
+// Parses the given command line. On success, out param 'command' contains
+// the user specified command.
+//
+// Returns:
+// TRUE: If the command line is valid
+// FALSE: otherwise
+static BOOL ParseCommandLine(__in int argc,
+ __in wchar_t *argv[],
+ __out HardLinkCommandOption *command)
+{
+ *command = HardLinkInvalid;
+
+ if (argc != 3 && argc != 4) {
+ return FALSE;
+ }
+
+ if (argc == 3) {
+ if (wcscmp(argv[0], L"hardlink") != 0 || wcscmp(argv[1], L"stat") != 0)
+ {
+ return FALSE;
+ }
+
+ *command = HardLinkStat;
+ }
+
+ if (argc == 4) {
+ if (wcscmp(argv[0], L"hardlink") != 0 || wcscmp(argv[1], L"create") != 0)
+ {
+ return FALSE;
+ }
+
+ *command = HardLinkCreate;
+ }
+
+ assert(*command != HardLinkInvalid);
+
+ return TRUE;
+}
+
+//----------------------------------------------------------------------------
+// Function: HardlinkStat
+//
+// Description:
+// Computes the number of hard links for a given file.
+//
+// Returns:
+// ERROR_SUCCESS: On success
+// error code: otherwise
+static DWORD HardlinkStat(__in LPCWSTR fileName, __out DWORD *puHardLinkCount)
+{
+ BY_HANDLE_FILE_INFORMATION fileInformation;
+ DWORD dwErrorCode = ERROR_SUCCESS;
+ PWSTR longFileName = NULL;
+
+ // First convert input paths to long paths
+ //
+ dwErrorCode = ConvertToLongPath(fileName, &longFileName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto HardlinkStatExit;
+ }
+
+ // Get file information which contains the hard link count
+ //
+ dwErrorCode = GetFileInformationByName(longFileName, FALSE, &fileInformation);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto HardlinkStatExit;
+ }
+
+ *puHardLinkCount = fileInformation.nNumberOfLinks;
+
+HardlinkStatExit:
+ LocalFree(longFileName);
+
+ return dwErrorCode;
+}
+
+//----------------------------------------------------------------------------
+// Function: HardlinkCreate
+//
+// Description:
+// Creates a hard link for a given file under the given name.
+//
+// Returns:
+// ERROR_SUCCESS: On success
+// error code: otherwise
+static DWORD HardlinkCreate(__in LPCWSTR linkName, __in LPCWSTR fileName)
+{
+ PWSTR longLinkName = NULL;
+ PWSTR longFileName = NULL;
+ DWORD dwErrorCode = ERROR_SUCCESS;
+
+ // First convert input paths to long paths
+ //
+ dwErrorCode = ConvertToLongPath(linkName, &longLinkName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto HardlinkCreateExit;
+ }
+
+ dwErrorCode = ConvertToLongPath(fileName, &longFileName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto HardlinkCreateExit;
+ }
+
+ // Create the hard link
+ //
+ if (!CreateHardLink(longLinkName, longFileName, NULL))
+ {
+ dwErrorCode = GetLastError();
+ }
+
+HardlinkCreateExit:
+ LocalFree(longLinkName);
+ LocalFree(longFileName);
+
+ return dwErrorCode;
+}
+
+//----------------------------------------------------------------------------
+// Function: Hardlink
+//
+// Description:
+// Creates a hard link for a given file under the given name. Outputs the
+// appropriate information to stdout on success, or stderr on failure.
+//
+// Returns:
+// EXIT_SUCCESS: On success
+// EXIT_FAILURE: otherwise
+int Hardlink(int argc, wchar_t *argv[])
+{
+ DWORD dwErrorCode = ERROR_SUCCESS;
+ int ret = EXIT_FAILURE;
+ HardLinkCommandOption command = HardLinkInvalid;
+
+ if (!ParseCommandLine(argc, argv, &command)) {
+ dwErrorCode = ERROR_INVALID_COMMAND_LINE;
+
+ fwprintf(stderr, L"Incorrect command line arguments.\n\n");
+ HardlinkUsage();
+ goto HardLinkExit;
+ }
+
+ if (command == HardLinkStat)
+ {
+ // Compute the number of hard links
+ //
+ DWORD uHardLinkCount = 0;
+ dwErrorCode = HardlinkStat(argv[2], &uHardLinkCount);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"HardlinkStat", dwErrorCode);
+ goto HardLinkExit;
+ }
+
+ // Output the result
+ //
+ fwprintf(stdout, L"%d\n", uHardLinkCount);
+
+ } else if (command == HardLinkCreate)
+ {
+ // Create the hard link
+ //
+ dwErrorCode = HardlinkCreate(argv[2], argv[3]);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ ReportErrorCode(L"HardlinkCreate", dwErrorCode);
+ goto HardLinkExit;
+ }
+
+ // Output the success message
+ //
+ fwprintf(stdout, L"Hardlink created for %s <<===>> %s\n", argv[2], argv[3]);
+
+ } else
+ {
+ // Should not happen
+ //
+ assert(FALSE);
+ }
+
+ ret = EXIT_SUCCESS;
+
+HardLinkExit:
+
+ return ret;
+}
+
+void HardlinkUsage()
+{
+ fwprintf(stdout, L"\
+Usage: hardlink create [LINKNAME] [FILENAME] |\n\
+ hardlink stat [FILENAME]\n\
+Creates a new hardlink on the existing file or displays the number of links\n\
+for the given file\n");
+}
\ No newline at end of file
Added: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h?rev=1453486&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h (added)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h Wed Mar 6 19:15:18 2013
@@ -0,0 +1,142 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#ifndef UNICODE
+#define UNICODE
+#endif
+
+#pragma once
+
+#include <stdio.h>
+#include <assert.h>
+#include <windows.h>
+#include <aclapi.h>
+#include <accctrl.h>
+#include <tchar.h>
+#include <strsafe.h>
+#include <lm.h>
+
+enum EXIT_CODE
+{
+ /* Common success exit code shared among all utilities */
+ SUCCESS = EXIT_SUCCESS,
+ /* Generic failure exit code share among all utilities */
+ FAILURE = EXIT_FAILURE,
+ /* Failure code indicates the user does not privilege to create symlinks */
+ SYMLINK_NO_PRIVILEGE = 2,
+};
+
+
+/*
+ * The array of 12 months' three-letter abbreviations
+ */
+extern const LPCWSTR MONTHS[];
+
+/*
+ * The Unix masks
+ * The Windows version of <sys/stat.h> does not contain all the POSIX flag/mask
+ * definitions. The following masks are used in 'winutils' to represent POSIX
+ * permission mode.
+ *
+ */
+enum UnixAclMask
+{
+ UX_O_EXECUTE = 00001, // S_IXOTH
+ UX_O_WRITE = 00002, // S_IWOTH
+ UX_O_READ = 00004, // S_IROTH
+ UX_G_EXECUTE = 00010, // S_IXGRP
+ UX_G_WRITE = 00020, // S_IWGRP
+ UX_G_READ = 00040, // S_IRGRP
+ UX_U_EXECUTE = 00100, // S_IXUSR
+ UX_U_WRITE = 00200, // S_IWUSR
+ UX_U_READ = 00400, // S_IRUSR
+ UX_DIRECTORY = 0040000, // S_IFDIR
+ UX_SYMLINK = 0120000, // S_IFLNK
+};
+
+
+/*
+ * The WindowsAclMask and WinMasks contain the definitions used to establish
+ * the mapping between Unix and Windows.
+ */
+enum WindowsAclMask
+{
+ WIN_READ, // The permission(s) that enable Unix read permission
+ WIN_WRITE, // The permission(s) that enable Unix write permission
+ WIN_EXECUTE, // The permission(s) that enbale Unix execute permission
+ WIN_OWNER_SE, // The permissions that are always set for file owners
+ WIN_ALL, // The permissions that all files on Windows should have
+ WIN_MASKS_TOTAL
+};
+extern const ACCESS_MASK WinMasks[];
+
+
+int Ls(int argc, wchar_t *argv[]);
+void LsUsage(LPCWSTR program);
+
+int Chmod(int argc, wchar_t *argv[]);
+void ChmodUsage(LPCWSTR program);
+
+int Chown(int argc, wchar_t *argv[]);
+void ChownUsage(LPCWSTR program);
+
+int Groups(int argc, wchar_t *argv[]);
+void GroupsUsage(LPCWSTR program);
+
+int Hardlink(int argc, wchar_t *argv[]);
+void HardlinkUsage();
+
+int Task(int argc, wchar_t *argv[]);
+void TaskUsage();
+
+int Symlink(int argc, wchar_t *argv[]);
+void SymlinkUsage();
+
+int SystemInfo();
+void SystemInfoUsage();
+
+DWORD GetFileInformationByName(__in LPCWSTR pathName, __in BOOL followLink,
+ __out LPBY_HANDLE_FILE_INFORMATION lpFileInformation);
+
+DWORD ConvertToLongPath(__in PCWSTR path, __deref_out PWSTR *newPath);
+
+DWORD GetSidFromAcctNameW(LPCWSTR acctName, PSID* ppSid);
+
+DWORD GetAccntNameFromSid(PSID pSid, LPWSTR *ppAcctName);
+
+void ReportErrorCode(LPCWSTR func, DWORD err);
+
+BOOL IsDirFileInfo(const BY_HANDLE_FILE_INFORMATION *fileInformation);
+
+DWORD FindFileOwnerAndPermission(
+ __in LPCWSTR pathName,
+ __out_opt LPWSTR *pOwnerName,
+ __out_opt LPWSTR *pGroupName,
+ __out_opt PINT pMask);
+
+DWORD DirectoryCheck(__in LPCWSTR pathName, __out LPBOOL result);
+
+DWORD SymbolicLinkCheck(__in LPCWSTR pathName, __out LPBOOL result);
+
+DWORD JunctionPointCheck(__in LPCWSTR pathName, __out LPBOOL result);
+
+DWORD ChangeFileModeByMask(__in LPCWSTR path, INT mode);
+
+DWORD GetLocalGroupsForUser(__in LPCWSTR user,
+ __out LPLOCALGROUP_USERS_INFO_0 *groups, __out LPDWORD entries);
+
+BOOL EnablePrivilege(__in LPCWSTR privilegeName);
\ No newline at end of file