HOWTO: Create Hard Links in Windows NT and Windows 2000ID: Q234727
|
Windows NT and Windows 2000 support hard links on NTFS disk volumes. Following are two programmatic approaches that exist for creating hard links:
A hard link is a directory entry for a file. Every file can be considered to have at least one hard link. On NTFS volumes, each file can have multiple hard links, and thus a single file can appear in many directories (or even in the same directory with different names). Since all of the links reference the same file, applications can open any of the links and modify the file. A file is deleted from the file system only after all links to it have been deleted.
Once a hard link is created, applications can use it like any other file name. Therefore, you can use the full Win32 file I/O API to access a file through a link. The changes made to a file through one link will be reflected by all other links (because they point to the same file). To remove a link use DeleteFile().
Hard links are supported on NTFS only; they may not be created on FAT or
FAT32 volumes. In addition, a hard link must reside on the same volume as
the file it references. You cannot create a hard link on one volume that points to a file on another volume. This is because a hard link is a directory entry that points to a file.
The security descriptor for a file belongs to the file, not the links that reference it. Thus, all links to a file grant the same access to the file. If the security descriptor for the file is changed by using one link, all other links will reflect that change.
The hard links created with BackupWrite() and CreateHardLink() are identical; the only difference is in the functions the applications call to create them. Creating hard links with BackupWrite() is supported on Windows 2000 and should be used when your application must also run on Windows NT version 4.0 and earlier. If your application is designed to run on Windows 2000, use CreateHardLink() because it is easier to use.
/*
Set security descriptor argument to NULL to leave file's security
descriptor alone.
*/
fCreatedLink = CreateHardLink (pszNewLinkName, pszExistingFileName,
NULL);
if (!fCreatedLink)
// error occurred, handle it.
NOTE: PszExistingFileName can be the original filename, or any already-existing link to the file. After this code is executed, pszNewLinkName will refer to the file.
The following sample code demonstrates how to use BackupWrite() to create a hard link on an NTFS volume. Basically, it "restores" a link to the file.
/*++
Copyright (c) 1996-1999 Microsoft Corporation
Module Name:
ln.c
Abstract:
This module illustrates how to use the Win32 BackupWrite() API to
create hard links.
NOTE: The new link file name path must be supplied to the BackupWrite()Win32 API call in Unicode.
--*/
#ifndef UNICODE
#define UNICODE
#define _UNICODE
#endif
#include <windows.h>
#include <stdio.h>
#define RTN_OK 0
#define RTN_USAGE 1
#define RTN_ERROR 13
int __cdecl wmain( int argc, wchar_t *argv[] )
{
LPWSTR FileSource;
WCHAR FileLink[ MAX_PATH + 1 ];
LPWSTR FilePart;
HANDLE hFileSource;
WIN32_STREAM_ID StreamId;
DWORD dwBytesWritten;
LPVOID lpContext;
DWORD cbPathLen;
DWORD StreamHeaderSize;
BOOL bSuccess;
if (argc != 3)
{
printf("Usage: %ls <existing_source_file> <link_file>\n",
argv[0]);
return RTN_USAGE;
}
FileSource = argv[1];
//
// open existing file that we link to
//
hFileSource = CreateFile(
FileSource,
FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE
| FILE_SHARE_DELETE,
NULL, // sa
OPEN_EXISTING,
0,
NULL
);
if (hFileSource == INVALID_HANDLE_VALUE)
{
printf("CreateFile (source) error! (rc=%lu)\n", GetLastError());
return RTN_ERROR;
}
//
// validate and sanitize supplied link path and use the result
// the full path MUST be Unicode for BackupWrite
//
cbPathLen = GetFullPathNameW( argv[2], MAX_PATH, FileLink, &FilePart);
if (cbPathLen == 0)
{
printf("GetFullPathName error! (rc=%lu)\n", GetLastError());
return RTN_ERROR;
}
cbPathLen = (cbPathLen + 1) * sizeof(WCHAR); // adjust for byte count
//
// it might also be a good idea to verify the existence of the link,
// (and possibly bail), as the file specified in FileLink will be
// overwritten if it already exists
//
//
// prepare and write the WIN32_STREAM_ID out
//
lpContext = NULL;
StreamId.dwStreamId = BACKUP_LINK;
StreamId.dwStreamAttributes = 0;
StreamId.dwStreamNameSize = 0;
StreamId.Size.HighPart = 0;
StreamId.Size.LowPart = cbPathLen;
//
// compute length of variable size WIN32_STREAM_ID
//
StreamHeaderSize = (LPBYTE)&StreamId.cStreamName - (LPBYTE)&
StreamId+ StreamId.dwStreamNameSize ;
bSuccess = BackupWrite(
hFileSource,
(LPBYTE)&StreamId, // buffer to write
StreamHeaderSize, // number of bytes to write
&dwBytesWritten,
FALSE, // don't abort yet
FALSE, // don't process security
&lpContext
);
if (bSuccess)
{
//
// write out the buffer containing the path
//
bSuccess = BackupWrite(
hFileSource,
(LPBYTE)FileLink, // buffer to write
cbPathLen, // number of bytes to write
&dwBytesWritten,
FALSE, // don't abort yet
FALSE, // don't process security
&lpContext
);
//
// free context
//
BackupWrite(
hFileSource,
NULL, // buffer to write
0, // number of bytes to write
&dwBytesWritten,
TRUE, // abort
FALSE, // don't process security
&lpContext
);
}
CloseHandle( hFileSource );
if (!bSuccess)
{
printf("BackupWrite error! (rc=%lu)\n", GetLastError());
return RTN_ERROR;
}
return RTN_OK;
}
Additional query words: ln link symbolic hard POSIX
Keywords : kbAPI kbFileIO kbKernBase
Version : winnt:3.51,4.0
Platform : winnt
Issue type : kbhowto
Last Reviewed: June 16, 1999