638801cce1
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1453486 13f79535-47bb-0310-9956-ffa450edef68
230 lines
5.6 KiB
C
230 lines
5.6 KiB
C
/**
|
|
* 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");
|
|
} |