Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Создание hardlink и symbolic link

Delphi , Файловая система , Ярлыки

Создание hardlink и symbolic link

Автор: Alex Konshin
WEB-сайт: http://delphibase.endimus.com

{ **** UBPFD *********** by delphibase.endimus.com ****
>> Создание hardlink и symbolic link.

Исходный код утилиты, которая создает hard и symbolic links почти как в unix.
Hardlink можно создать только для файлов и только на NTFS.
Symbolic link можно создать только для директориев и только на NTFS5 (Win2K/XP)
и он не может указывать на сетевой ресурс.

Зависимости: Windows, SysUtils
Автор:       Alex Konshin, akonshin@earthlink.net, Boston, USA
Copyright:   http://home.earthlink.net/~akonshin/files/xlink.zip
Дата:        30 декабря 2002 г.
***************************************************** }

program xlink;

uses
  Windows, SysUtils;

{$APPTYPE CONSOLE}
{$R xlink.res}
type

  TOptions = set of (optSymbolicLink, optOverwrite, optRecursive, optDirectory);

  int64rec = packed record
    lo: LongWord;
    hi: LongInt;
  end;

const
  FILE_DOES_NOT_EXIST = DWORD(-1);

  //=============================================================

function isFileExists(const AFileName: string): Boolean;
var
  h: THandle;
  rFindData: TWin32FindData;
begin
  h := Windows.FindFirstFile(PChar(AFileName), rFindData);
  Result := h <> INVALID_HANDLE_VALUE;
  if not Result then
    Exit;
  Windows.FindClose(h);
  Result := (rFindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0;
end;
//-------------------------------------------------------------
// warning: function assumes that it is correct directory name

function isDirectoryEmpty(const ADirectoryName: string): Boolean;
var
  h: THandle;
  len: Integer;
  rFindData: TWin32FindData;
  sSeachMask: string;
begin
  len := Length(ADirectoryName);
  if (PChar(ADirectoryName) + len - 1)^ = '\' then
    sSeachMask := ADirectoryName + '*'
  else
    sSeachMask := ADirectoryName + '\*';
  h := Windows.FindFirstFile(PChar(sSeachMask), rFindData);
  Result := (h = INVALID_HANDLE_VALUE);
  Windows.FindClose(h);
end;

//-------------------------------------------------------------

function SysErrorMessage(ErrorCode: Integer): string;
var
  Len: Integer;
  Buffer: array[0..255] of Char;
begin
  Len := FormatMessage(
    FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ARGUMENT_ARRAY,
    nil, ErrorCode, 0, Buffer, SizeOf(Buffer), nil);
  while (Len > 0) and (Buffer[Len - 1] in [#0..' ', '.']) do
    Dec(Len);
  SetString(Result, Buffer, Len);
end;

//-------------------------------------------------------------

procedure _CreateHardlink(AFileName: string; AFileWCName: PWideChar; ALinkName:
  string; overwrite: Boolean);
var
  aLinkWCFileName, aLinkFullName: array[0..MAX_PATH] of WChar;
  pwFilePart: LPWSTR;
  hFileSource: THandle;
  rStreamId: WIN32_STREAM_ID;
  cbPathLen, dwStreamHeaderSize, dwBytesWritten: DWORD;
  lpContext: Pointer;
begin
  StringToWidechar(ALinkName, aLinkWCFileName, MAX_PATH);

  hFileSource :=
    Windows.CreateFile(
    PChar(AFileName),
    GENERIC_READ or GENERIC_WRITE,
    FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
    nil,
    OPEN_EXISTING,
    0,
    0
    );

  if hFileSource = INVALID_HANDLE_VALUE then
    raise Exception.Create('Can''t open file "' + AFileName + '"');

  try
    cbPathLen := Windows.GetFullPathNameW(aLinkWCFileName, MAX_PATH,
      aLinkFullName, pwFilePart);
    if cbPathLen <= 0 then
      raise Exception.Create('Invalid link name "' + ALinkName + '"');

    cbPathLen := (cbPathLen + 1) * SizeOf(WChar);

    lpContext := nil;

    rStreamId.dwStreamId := BACKUP_LINK;
    rStreamId.dwStreamAttributes := 0;
    rStreamId.dwStreamNameSize := 0;
    int64rec(rStreamId.Size).hi := 0;
    int64rec(rStreamId.Size).lo := cbPathLen;
    dwStreamHeaderSize := PChar(@rStreamId.cStreamName) - PChar(@rStreamId)
      + LongInt(rStreamId.dwStreamNameSize);

    if not BackupWrite(
      hFileSource,
      Pointer(@rStreamId), // buffer to write
      dwStreamHeaderSize, // number of bytes to write
      dwBytesWritten,
      False, // don't abort yet
      False, // don't process security
      lpContext
      ) then
      RaiseLastOSError;

    if not BackupWrite(
      hFileSource,
      Pointer(@aLinkFullName), // buffer to write
      cbPathLen, // number of bytes to write
      dwBytesWritten,
      False, // don't abort yet
      False, // don't process security
      lpContext
      ) then
      RaiseLastOSError;

    // free context
    if not BackupWrite(
      hFileSource,
      nil, // buffer to write
      0, // number of bytes to write
      dwBytesWritten,
      True, // abort
      False, // don't process security
      lpContext
      ) then
      RaiseLastOSError;

  finally
    CloseHandle(hFileSource);
  end;
end;

//-------------------------------------------------------------
// ADirName and ADirForLinks must not end with backslach

procedure _CreateHardlinksForSubDirectory(const ADirName, ADirForLinks: string;
  options: TOptions);
var
  h: THandle;
  sExistedFile, sLinkName: string;
  dwAttributes: DWORD;
  rFindData: TWin32FindData;
  awcFileName: array[0..MAX_PATH] of WChar;
begin
  dwAttributes := GetFileAttributes(PChar(ADirForLinks));
  if dwAttributes = FILE_DOES_NOT_EXIST then
  begin
    // WriteLn('Create Directory ',ADirForLinks);
    if not CreateDir(ADirForLinks) then
      raise Exception.Create('Can''t create directory "' + ADirForLinks + '".');
  end
  else if (dwAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
    raise Exception.Create('File "' + ADirName
      + '" already exists and it is not a directory.');
  h := Windows.FindFirstFile(PChar(ADirName + '\*'), rFindData);
  if h = INVALID_HANDLE_VALUE then
    Exit;
  try
    repeat
      if (rFindData.cFileName[0] = '.') and
        ((rFindData.cFileName[1] = #0) or ((rFindData.cFileName[1] = '.') and
        (rFindData.cFileName[2] = #0))) then
        Continue;
      sExistedFile := ADirName + '\' + rFindData.cFileName;
      sLinkName := ADirForLinks + '\' + rFindData.cFileName;
      if (rFindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
      begin

        awcFileName[
          Windows.MultiByteToWideChar(0, 0, PChar(sExistedFile),
          MAX_PATH, awcFileName, MAX_PATH)
          ] := #0;

        _CreateHardlink(sExistedFile, awcFileName, sLinkName,
          optOverwrite in options);
      end
      else if optRecursive in options then
      begin
        _CreateHardlinksForSubDirectory(sExistedFile, sLinkName, options);
      end;

    until not Windows.FindNextFile(h, rFindData);
  finally
    Windows.FindClose(h);
  end;
end;

//-------------------------------------------------------------

procedure CreateHardlink(AFileName, ALinkName: string; options: TOptions);
var
  dwAttributes: DWORD;
  aFileSource: array[0..MAX_PATH] of WChar;
begin
  dwAttributes := Windows.GetFileAttributes(PChar(AFileName));
  if dwAttributes = FILE_DOES_NOT_EXIST then
    raise Exception.Create('File "' + AFileName + '" does not exist.');
  if (dwAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0 then
    raise Exception.Create('Can''t create hardlink for directory (file "'
      + AFileName + '").');

  dwAttributes := Windows.GetFileAttributes(PChar(ALinkName));
  if dwAttributes <> FILE_DOES_NOT_EXIST then
  begin
    if not (optOverwrite in options) then
      raise Exception.Create('File "' + ALinkName + '" already exists.');
    if (dwAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0 then
      raise Exception.Create('Can''t overwrite directory "' + AFileName + '".');
  end;

  StringToWidechar(AFileName, aFileSource, MAX_PATH);
  _CreateHardlink(AFileName, aFileSource, ALinkName, optOverwrite in options);

end;

//-------------------------------------------------------------

procedure CreateHardlinksForDirectory(const ADirName, ADirForLinks: string;
  options: TOptions);
var
  dwAttributes: DWORD;
  len: Integer;
  sDirName, sDirForLinks: string;
begin
  dwAttributes := Windows.GetFileAttributes(PChar(ADirName));
  if dwAttributes = FILE_DOES_NOT_EXIST then
    raise Exception.Create('Directory "' + ADirName + '" does not exist.');
  if (dwAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
    raise Exception.Create('File "' + ADirName + '" is not a directory.');
  len := Length(ADirName);
  if (PChar(ADirName) + len - 1)^ = '\' then
    sDirName := Copy(ADirName, 1, len - 1)
  else
    sDirName := ADirName;
  if (PChar(ADirForLinks) + Length(ADirForLinks) - 1)^ <> '\' then
    sDirForLinks := ADirForLinks
  else
    sDirForLinks := Copy(ADirForLinks, 1, Length(ADirForLinks) - 1);
  _CreateHardlinksForSubDirectory(sDirName, sDirForLinks, options);
end;

//-------------------------------------------------------------

procedure CreateHardlinksInDirectory(const AFileName, ADirForLinks: string;
  options: TOptions);
var
  dwAttributes: DWORD;
  len: Integer;
  sFileName, sDirForLinks, sLinkName: string;
  aFileSource: array[0..MAX_PATH] of WChar;
begin
  dwAttributes := Windows.GetFileAttributes(PChar(AFileName));
  if dwAttributes = FILE_DOES_NOT_EXIST then
    raise Exception.Create('File or directory "' + AFileName +
      '" does not exist.');
  if (dwAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
  begin

    sLinkName := ADirForLinks + '\' + SysUtils.ExpandFileName(AFileName);
    dwAttributes := Windows.GetFileAttributes(PChar(sLinkName));
    if dwAttributes <> FILE_DOES_NOT_EXIST then
    begin
      if not (optOverwrite in options) then
        raise Exception.Create('File "' + sLinkName + '" already exists.');
      if (dwAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0 then
        raise Exception.Create('Can''t overwrite directory "' + AFileName +
          '".');
    end;
    StringToWidechar(AFileName, aFileSource, MAX_PATH);
    _CreateHardlink(AFileName, aFileSource, sLinkName,
      optOverwrite in options);

  end
  else
  begin
    len := Length(AFileName);
    if (PChar(AFileName) + len - 1)^ = '\' then
      sFileName := Copy(AFileName, 1, len - 1)
    else
      sFileName := AFileName;
    if (PChar(ADirForLinks) + Length(ADirForLinks) - 1)^ <> '\' then
      sDirForLinks := ADirForLinks
    else
      sDirForLinks := Copy(ADirForLinks, 1, Length(ADirForLinks) - 1);
    _CreateHardlinksForSubDirectory(sFileName, sDirForLinks, options);
  end;
end;

//-------------------------------------------------------------

procedure DeleteDirectoryContent(const ADirName: string);
type
  PDirRef = ^TDirRef;
  PPDirRef = ^PDirRef;
  TDirRef = record
    Next: PDirRef;
    DirName: string;
  end;
var
  h: THandle;
  sFileName: string;
  pSubDirs: PDirRef;
  ppLast: PPDirRef;
  pDir: PDirRef;
  rFindData: TWin32FindData;
begin
  pSubDirs := nil;
  ppLast := @pSubDirs;
  h := Windows.FindFirstFile(PChar(ADirName + '\*'), rFindData);
  if h = INVALID_HANDLE_VALUE then
    Exit;
  try
    try
      repeat
        if (rFindData.cFileName[0] = '.') and
          ((rFindData.cFileName[1] = #0) or ((rFindData.cFileName[1] = '.') and
          (rFindData.cFileName[2] = #0))) then
          Continue;
        sFileName := ADirName + '\' + rFindData.cFileName;
        if (rFindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0 then
        begin
          New(pDir);
          with pDir^ do
          begin
            Next := nil;
            DirName := sFileName;
          end;
          ppLast^ := pDir;
          ppLast := @pDir^.Next;
        end
        else if not DeleteFile(sFileName) then
          raise Exception.Create('Can''t delete file "' + sFileName + '".');

      until not Windows.FindNextFile(h, rFindData);
    finally
      Windows.FindClose(h);
    end;
    if pSubDirs <> nil then
    begin
      repeat
        pDir := pSubDirs;
        pSubDirs := pDir^.Next;
        sFileName := pDir^.DirName;
        Dispose(pDir);
        DeleteDirectoryContent(sFileName);
        if not RemoveDir(sFileName) then
          raise Exception.Create('Can''t delete directory "' + sFileName +
            '".');
      until pSubDirs = nil;
    end;
  except
    while pSubDirs <> nil do
    begin
      pDir := pSubDirs;
      pSubDirs := pDir^.Next;
      Dispose(pDir);
    end;
    raise;
  end;
end;

//-------------------------------------------------------------
const
  FILE_DEVICE_FILE_SYSTEM = $0009;
  // Define the method codes for how buffers are passed for I/O and FS controls
  METHOD_BUFFERED = 0;
  METHOD_IN_DIRECT = 1;
  METHOD_OUT_DIRECT = 2;
  METHOD_NEITHER = 3;

  // Define the access check value for any access
  FILE_ANY_ACCESS = 0;
  FILE_READ_DATA = 1;
  FILE_WRITE_DATA = 2;

  FSCTL_SET_REPARSE_POINT = (FILE_DEVICE_FILE_SYSTEM shl 16) or
    (FILE_ANY_ACCESS shl 14) or (41 shl 2) or (METHOD_BUFFERED);
  FSCTL_GET_REPARSE_POINT = (FILE_DEVICE_FILE_SYSTEM shl 16) or
    (FILE_ANY_ACCESS shl 14) or (42 shl 2) or (METHOD_BUFFERED);
  FSCTL_DELETE_REPARSE_POINT = (FILE_DEVICE_FILE_SYSTEM shl 16) or
    (FILE_ANY_ACCESS shl 14) or (43 shl 2) or (METHOD_BUFFERED);

  FILE_FLAG_OPEN_REPARSE_POINT = $00200000;

  FILE_ATTRIBUTE_REPARSE_POINT = $00000400;

  IO_REPARSE_TAG_MOUNT_POINT = $A0000003;

  REPARSE_MOUNTPOINT_HEADER_SIZE = 8;

type
  REPARSE_MOUNTPOINT_DATA_BUFFER = packed record
    ReparseTag: DWORD;
    ReparseDataLength: DWORD;
    Reserved: Word;
    ReparseTargetLength: Word;
    ReparseTargetMaximumLength: Word;
    Reserved1: Word;
    ReparseTarget: array[0..0] of WChar;
  end;
  TReparseMountpointDataBuffer = REPARSE_MOUNTPOINT_DATA_BUFFER;
  PReparseMountpointDataBuffer = ^TReparseMountpointDataBuffer;

  //-------------------------------------------------------------

function CreateSymlink(ATargetName, ALinkName: string; const options: TOptions):
  Boolean;
const
  pwcNativeFileNamePrefix: PWideChar = '\??\';
  nNativeFileNamePrefixWCharLength = 4;
  nNativeFileNamePrefixByteLength = nNativeFileNamePrefixWCharLength * 2;
var
  hLink: THandle;
  pReparseInfo: PReparseMountpointDataBuffer;
  len, size: Integer;
  pwcLinkFileName: PWideChar;
  pwcTargetNativeFileName: PWideChar;
  pwcTargetFileName: PWideChar;
  pwc: PWideChar;
  pc: PChar;
  dwBytesReturned: DWORD;
  dwAttributes: DWORD;
  bDirectoryCreated: Boolean;
  aTargetFullName: array[0..MAX_PATH] of Char;
begin
  Result := False;
  pReparseInfo := nil;
  hLink := INVALID_HANDLE_VALUE;
  bDirectoryCreated := False;

  len := Length(ALinkName);
  if ((PChar(ALinkName) + len - 1)^ = '\') and ((PChar(ALinkName) + len - 2)^ <>
    ':') then
  begin
    Dec(len);
    SetLength(ALinkName, len);
  end;

  System.GetMem(pwcLinkFileName, len + len + 2);
  try
    pwcLinkFileName[
      Windows.MultiByteToWideChar(0, 0, PChar(ALinkName), len, wcLinkFileName,
        len)
      ] := #0;

    dwAttributes := Windows.getFileAttributesW(pwcLinkFileName);
    if dwAttributes <> FILE_DOES_NOT_EXIST then
    begin
      if not (optOverwrite in options) then
      begin
        if (dwAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
          raise Exception.Create('The file "' + ALinkName + '" already exists');
        if not isDirectoryEmpty(ALinkName) then
          raise Exception.Create(
            'The directory "' + ALinkName +
              '" already exists and is not empty');
        dwAttributes := FILE_DOES_NOT_EXIST;
      end
      else if ((dwAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0) then
      begin
        if not DeleteFile(ALinkName) then
          raise Exception.Create('Can''t overwrite file "' + ALinkName + '"');
        dwAttributes := FILE_DOES_NOT_EXIST;
      end
      else if (dwAttributes and FILE_ATTRIBUTE_REPARSE_POINT)
        <> FILE_ATTRIBUTE_REPARSE_POINT then
        if not isDirectoryEmpty(ALinkName) then
        begin
          if not (optDirectory in options) then
            raise Exception.Create('Can''t overwrite non-empty directory "'
              + ALinkName + '"');
          DeleteDirectoryContent(ALinkName);
        end;
    end;
    if dwAttributes = FILE_DOES_NOT_EXIST then
    begin
      Windows.CreateDirectoryW(pwcLinkFileName, nil);
      bDirectoryCreated := True;
    end;

    try
      hLink := Windows.CreateFileW(pwcLinkFileName, GENERIC_WRITE, 0, nil,
        OPEN_EXISTING,
        FILE_FLAG_OPEN_REPARSE_POINT or FILE_FLAG_BACKUP_SEMANTICS, 0);

      if hLink = INVALID_HANDLE_VALUE then
        RaiseLastOSError;

      len := Length(ATargetName);
      if ((PChar(ATargetName) + len - 1)^ = '\')
        and ((PChar(ATargetName) + len - 2)^ <> ':') then
      begin
        Dec(len);
        SetLength(ATargetName, len);
      end;

      len := Windows.GetFullPathName(PChar(ATargetName), MAX_PATH,
        aTargetFullName, pc);

      size := len + len + 2
        + nNativeFileNamePrefixByteLength + REPARSE_MOUNTPOINT_HEADER_SIZE + 12;
      System.GetMem(pReparseInfo, size);
      FillChar(pReparseInfo^, size, #0);

      pwcTargetNativeFileName := @pReparseInfo^.ReparseTarget;
      System.Move(pwcNativeFileNamePrefix^, pwcTargetNativeFileName^,
        nNativeFileNamePrefixByteLength + 2);
      pwcTargetFileName := pwcTargetNativeFileName +
        nNativeFileNamePrefixWCharLength;
      pwc := pwcTargetFileName + Windows.MultiByteToWideChar(0, 0,
        aTargetFullName, len, pwcTargetFileName, len);
      pwc^ := #0;

      with pReparseInfo^ do
      begin
        ReparseTag := IO_REPARSE_TAG_MOUNT_POINT;
        ReparseTargetLength := PChar(pwc) - PChar(pwcTargetNativeFileName);
        ReparseTargetMaximumLength := ReparseTargetLength + 2;
        ReparseDataLength := ReparseTargetLength + 12;
      end;

      dwBytesReturned := 0;
      if not DeviceIoControl(hLink, FSCTL_SET_REPARSE_POINT, pReparseInfo,
        pReparseInfo^.ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE,
        nil, 0, dwBytesReturned, nil) then
        RaiseLastOSError;

    except
      if bDirectoryCreated then
        RemoveDirectoryW(pwcLinkFileName);
      raise;
    end;

    Result := true;

  finally
    if hLink <> INVALID_HANDLE_VALUE then
      Windows.CloseHandle(hLink);
    if pwcLinkFileName <> nil then
      System.FreeMem(pwcLinkFileName);
    if pReparseInfo <> nil then
      System.FreeMem(pReparseInfo);
  end;

end;

//-------------------------------------------------------------

procedure Help;
begin
  WriteLn;
  WriteLn('Create link(s) on NTFS.');
  WriteLn;
  WriteLn('Usage:');
  WriteLn;
  WriteLn('To create hardlink(s) (works only for files):');
  WriteLn('xlink [-fr] <existed_file> <link_name>');
  WriteLn;
  WriteLn('To create symbolic link (works on Windows 2k/XP for directories only):');
  WriteLn('xlink -s[f|F] <existed_directory> <link_name>');
  WriteLn;
  WriteLn('Options:');
  WriteLn('-f Overwrite file with name <link_name> if it exists.');
  WriteLn('-F Overwrite file/directory with name <link_name> if it exists.');
  WriteLn('-r Recursive.');
  WriteLn;
  WriteLn('(c) 2002 Alex Konshin');
  Halt;
end;
//-------------------------------------------------------------

procedure Execute;
var
  iArg: Integer;
  sArg: string;
  ptr: PChar;
  options: TOptions;
  sExistedFileName: string;
  sLink: string;
  dwAttrs: DWORD;
begin
  iArg := 1;
  repeat
    sArg := ParamStr(iArg);
    if sArg = '' then
      Help;
    if PChar(sArg)^ <> '-' then
      Break;
    ptr := PChar(sArg) + 1;
    while ptr^ <> #0 do
    begin
      case ptr^ of
        's', 'S': Include(options, optSymbolicLink);
        'h', 'H': Help;
        'F': options := options + [optOverwrite, optDirectory];
        'f': Include(options, optOverwrite);
        'r', 'R': Include(options, optRecursive);
        'd', 'D': Include(options, optDirectory);
      else
        WriteLn('Error: Invalid option ''-', ptr^, '''');
        Exit;
      end;
      Inc(ptr);
    end;
    Inc(iArg);
  until iArg <= ParamCount;

  if ParamCount <= iArg then
    Help;
  if ParamCount - iArg > 1 then
    Include(options, optDirectory);

  if optSymbolicLink in options then
  begin
    sLink := ParamStr(ParamCount);
    repeat
      sExistedFileName := ParamStr(iArg);
      if not CreateSymlink(sExistedFileName, sLink, options) then
        WriteLn('The symbolic link creation failed.');
      Inc(iArg);
    until iArg >= ParamCount;
  end
  else if (options * [optRecursive, optDirectory]) <> [] then
  begin

    sLink := ParamStr(ParamCount);
    repeat
      sExistedFileName := ParamStr(iArg);
      CreateHardlinksInDirectory(sExistedFileName, sLink, options);

      Inc(iArg);
    until iArg >= ParamCount;

  end
  else
  begin

    sExistedFileName := ParamStr(iArg);
    sLink := ParamStr(ParamCount);
    dwAttrs := GetFileAttributes(PChar(sExistedFileName));

    if dwAttrs = FILE_DOES_NOT_EXIST then
    begin
      writeln('Error: The source file does not exist');
      Exit;
    end;
    if (dwAttrs and FILE_ATTRIBUTE_DIRECTORY) <> 0 then
    begin
      writeln('Error: Can''t create hardlink for directory');
      Exit;
    end;
    CreateHardlink(sExistedFileName, sLink, options);
  end;

end;

//=============================================================
begin
  if ParamCount < 2 then
    Help;
  try
    Execute;
  except
    on E: Exception do
    begin
      WriteLn(E.ClassName + ': ' + E.Message);
    end;
  end;
end.

Программа на Delphi для создания жёстких ссылок и символических ссылок на файловых системах NTFS.

Структура программы Программа состоит из нескольких процедур: 1. CreateHardlink: Создает жёсткую ссылку для файла. 2. CreateHardlinksForSubDirectory: Создает жёсткие ссылки для всех файлов в директории и ее поддиректориях. 3. CreateSymlink: Создает символическую ссылку для директории. 4. DeleteDirectoryContent: Удаляет содержимое директории. 5. Help: Отображает информацию о помощи.

Главная процедура Главная процедура, Execute, отвечает за парсинг аргументов командной строки и вызывает соответствующие процедуры для создания жёстких ссылок или символических ссылок. Она также обрабатывает опции, такие как перезапись, рекурсивность и создание директории.

Опции Программа поддерживает несколько опций: 1. -f или --force: Перезаписать существующий файл с тем же именем. 2. -F или --force-directory: Перезаписать существующую директорию с тем же именем. 3. -r или --recursive: Создавать жёсткие ссылки для всех файлов в директории и ее поддиректориях. 4. -s или --symbolic-link: Создавать символическую ссылку вместо жёсткой.

Обработка ошибок Программа использует исключения для обработки ошибок, таких как файл не найден, недопустимая опция или неудача создания ссылки.

Ограничения NTFS Программа предназначена для файловых систем NTFS и имеет некоторые ограничения: 1. Жёсткие ссылки могут быть созданы только для файлов, а не для директорий. 2. Символические ссылки могут быть созданы только для директорий на Windows 2000/XP. 3. Программа не поддерживает создание жёстких ссылок или символических ссылок на сетевых ресурсах.

Стиль кода Код написан в стиле, согласном с синтаксисом Pascal Delphi, и использует отступы и пробелы для улучшения читаемости. Однако некоторые части кода могут потребовать комментариев и дополнительной обработки ошибок.

Создание hardlink и symbolic link на NTFS. В статье описывается утилита, которая позволяет создавать hardlinks и symbolic links на файловой системе NTFS. Hardlinks - это ссылки на файлы, которые не зависят от имени файла, а символические


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Ярлыки ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 11:47:22/0.0072588920593262/1