Aqui está um comportamento estranho que encontrei com o mklink
Windows desde o Vista. Suspeito que possa haver um defeito mklink
ou mesmo a profundidade do driver do sistema de arquivos NTFS, mas o comportamento pode usar alguma explicação. Esse comportamento foi encontrado no Windows 7 e 10, respectivamente.
Suponha que tenhamos um diretório em um volume NTFS ( NÃO tente isso em nada além do volume que você está criando para esse único propósito!) E um arquivo nomeado bar.txt
dentro dele.
md F:\1
echo foo > F:\1\bar.txt
Agora, emita o seguinte comando (via prompt privilegiado):
mklink F:\1:bar F:\1\bar.txt
... o que deve lhe dar:
symbolic link created for F:\1:bar <<===>> F:\1\bar.txt
Não se preocupe, eu sei que isso é bobagem . Mas foi o resultado de um teste se um fluxo de dados alternativo (ADS) poderia se tornar um ponto de nova análise. Afirmei que não podia, porque um fluxo de dados alternativo só tem um nome, um tamanho e - bem - os dados dentro dele. Diferentemente de um arquivo ou diretório, ele não possui atributos de arquivo ou carimbos de data / hora e, portanto, não haveria nenhum atributo para designar o ADS como ponto de nova análise (o que de outra forma ocorre através dos atributos do arquivo). Ou de forma diferente: os pontos de nova análise podem se referir apenas às entradas do diretório (via $Extend\$Reparse
), enquanto o ADS está vinculado às entradas do diretório.
O resultado do comando acima é este:
F:\>dir /r
Volume in drive F is TEST
Volume Serial Number is 24F3-8A7D
Directory of F:\
2018-04-03 20:47 <SYMLINKD> 1 [F:\1\bar.txt]
0 1:bar:$DATA
0 File(s) 0 bytes
1 Dir(s) 4,244,283,392 bytes free
Não é de surpreender que tentar mudar para este diretório não funcione e produz The directory name is invalid.
Da mesma forma, a tentativa de excluir o ponto de nova análise usando junction -d
(do Sysinternals Suite) ou usando fsutil reparsepoint delete
falha com o mesmo erro. Somente a inspeção dos dados do ponto de nova análise me dá algo a que me apegar:
F:\>fsutil reparsepoint query F:\1
Reparse Tag Value : 0xa000000c
Tag value: Microsoft
Tag value: Name Surrogate
Tag value: Symbolic Link
Reparse Data Length: 0x00000044
Reparse Data:
0000: 18 00 20 00 00 00 18 00 00 00 00 00 46 00 3a 00 .. .........F.:.
0010: 5c 00 31 00 5c 00 62 00 61 00 72 00 2e 00 74 00 \.1.\.b.a.r...t.
0020: 78 00 74 00 5c 00 3f 00 3f 00 5c 00 46 00 3a 00 x.t.\.?.?.\.F.:.
0030: 5c 00 31 00 5c 00 62 00 61 00 72 00 2e 00 74 00 \.1.\.b.a.r...t.
0040: 78 00 74 00 x.t.
Agora, minha pergunta é o que aconteceu aqui e como me livrar de tal ponto de nova análise novamente com as ferramentas do Windows integradas (ou, na sua falta, com as externas)? Pontos de bônus por poder responder o que aconteceu com o arquivo dentro da pasta 1
e divulgar sua metodologia.
Minha teoria de trabalho até agora é a seguinte:
mklink
cria o "arquivo"F:\1:bar
e obtém êxito (presumivelmente viaCreateFile()
).mklink
define oREPARSE_DATA_BUFFER
"arquivo" criado que não pode funcionar, pois é um ADS em um diretório. Portanto, internamente, o que acontece é que o driver do sistema de arquivos define o buffer de dados de nova análise no diretório
O resultado é o que vemos. O que me incomoda aqui é que normalmente você não pode obter um identificador em um diretório sem especificar um sinalizador específico. Portanto, não apenas mklink
criamos um link simbólico em um diretório para um arquivo, mas também evitamos a necessidade de especificar FILE_FLAG_BACKUP_SEMANTICS
.
A documentação de FILE_FLAG_BACKUP_SEMANTICS
sob CreateFile
lê:
Você deve definir esse sinalizador para obter um identificador para um diretório. Um identificador de diretório pode ser passado para algumas funções em vez de um identificador de arquivo. Para mais informações, consulte a seção Comentários.
Para reproduzir, recomendo que você não tente fazer isso em uma unidade NTFS existente, mas crie um novo usando o driver de disco RAM do ImDisk e a imdisk
ferramenta de linha de comando que o acompanha (via prompt privilegiado):
imdisk -a -t vm -p "/fs:ntfs /q /y /v:TEST" -s 4G -m F:
(altere os parâmetros da forma que achar melhor. -m
indica uma letra de unidade e -s
o tamanho do disco RAM.)
fonte