Pular para o conteúdo principal

O SFTP é o subsistema FTP que faz parte do SSH, ele permite que você faça transferências de arquivos criptografados. Na última semana tive 2 problemas sobre o SFTP não transferir arquivos corretamente. Em um caso, OpenVOS era a fonte do arquivo e no outro caso, OpenVOS estava recebendo o arquivo. Em ambos os casos, os arquivos continham dados ASCII e os problemas tinham a ver com as diferenças entre Microsoft Windows e OpenVOS terminando linhas em um arquivo de texto.

Vamos começar com OpenVOS como a fonte. Se você criar um arquivo de texto usando seu editor favorito, você cria um arquivo seqüencial. Por exemplo

d test
%phx_vos#m16_mas>SysAdmin>Noah_Davids>test  10-09-05 08:13:49 mst
12345
67890

ready 08:13:49

Figura 1 - exibição de um arquivo de texto
O comando display_file_status mostra que é um arquivo seqüencial e que enquanto a contagem de bytes de dados é 10, na verdade há 20 bytes no arquivo.
display_file_status test
name: %phx_vos#m16_mas>SysAdmin>Noah_Davids>test
file organization: sequential file
. . .
next byte:                 20
blocks used: 1
. . .
record count: 2
data byte count:           10

ready 08:14:01

Figura 2 - display_file status
O comando dump_file mostra a estrutura real do arquivo. Cada "linha" é precedida e terminada com 2 bytes que indicam seu comprimento. Estes bytes de comprimento têm que começar em um limite de bytes pares para que haja também um byte de preenchimento. O que é significativo notar é que não há caracteres típicos de terminação de linha, seja uma seqüência de alimentação de linha (0x0A) ou uma seqüência de alimentação de linha de retorno de carro (0x0D0A).
dump_file test%phx_vos#m16_mas>SysAdmin>Noah_Davids>teste 10-09-05 08:14:07 mst
Bloco número 1000  00053132 333435FF 00050005 36373839 |..12345…..6789|010 30FF0005 FFFFFFFFFF FFFFFFFFFF FFFFFFFFFF |0...............|020 FFFFFFFFFFFF FFFFFFFFFFFF FFFFFFFFFF FFFFFFFFFF |................|

=

FF0 FFFFFFFF FFFFFFFFFF FFFFFFFFFF FFFFFFFF FFFFFFFF |................|

pronto 08:14:07

Figura 3 - dump_file mostrando a estrutura real do arquivo

 

Quando você transfere o arquivo usando SFTP, OpenVOS tira os bytes de comprimento da linha e acrescenta um caracter de alimentação de linha. O resultado é que enquanto o arquivo original continha 10 tipos de dados, o arquivo transferido contém 12.
C:Documents and SettingsnoahMy Documentstemp>"C:Program FilesPuTTYpsftp" nd@164.152.77.128
Using username "nd".
nd@164.152.77.128's password:
Remote working directory is /SysAdmin/Noah_Davids
psftp> get test test.txt
remote:/SysAdmin/Noah_Davids/test => local:test.txt
psftp> quit
C:Documents and SettingsnoahMy Documentstemp>dir
Volume in drive C has no label.
Volume Serial Number is 38B1-9C13
Directory of C:Documents and SettingsnoahMy Documentstempblog - sftp
08/27/2010 01:50 PM <DIR> .
08/27/2010 01:50 PM <DIR> ..
08/27/2010 01:50 PM 12 test.txt
1 File(s) 12 bytes
2 Dir(s) 39,471,644,672 bytes free
Figura 4 - O comprimento do arquivo transferido não corresponde ao comprimento do arquivo fonte
Além disso, se você exibir o arquivo em algo como o Bloco de Notas, ele será exibido como uma linha com símbolos engraçados onde as linhas devem terminar.
Figura 5 - exibição do arquivo no Bloco de Notas
Se você usar um utilitário para obter uma descarga hexadecimal do arquivo, você verá que no final de cada linha há um caractere de alimentação de linha (0x0A). A seqüência de terminação de linha padrão do Microsoft Windows é a alimentação de linha de retorno do carro (0x0D0A), o Notepad não sabe como interpretar apenas o caractere de alimentação de linha, embora existam outros editores que exibirão o arquivo corretamente.

 

Figura 6 - Hex dump do arquivo transferido
O resultado é que o arquivo transferido parece estar corrompido, o comprimento é diferente e você não pode exibi-lo - pelo menos no Bloco de Notas. Converter o arquivo em um arquivo stream antes de transferi-lo corrigirá a questão do comprimento; ambos os arquivos mostrarão agora o mesmo comprimento, mas a questão da terminação da linha permanecerá.

 

Agora e se o OpenVOS estiver recebendo um arquivo de um sistema Microsoft Windows? Como eu já disse, o Microsoft Windows usa uma seqüência de alimentação de linha de retorno para terminar uma linha.
Figura 7 - Hex dump de um arquivo criado em um sistema Microsoft Windows
O subsistema SFTP do OpenVOS criará um arquivo stream. Os caracteres de alimentação de linha serão tomados como caracteres de terminação de linha e os caracteres de retorno de carruagem serão tratados como parte dos dados da linha.

dump_file pc1.txt

%phx_vos#m16_mas>SysAdmin>Noah_Davids>pc1.txt 10-09-05 08:52:21 mst
Bloco número 1

000 61626364650D0A666768696A 0D0AFFFF|abcde..fghij....|

010 FFFFFFFF FFFFFFFFFF FFFFFFFFFF FFFFFFFF FFFFFFFF |................|

=

FF0 FFFFFFFF FFFFFFFFFF FFFFFFFFFF FFFFFFFF FFFFFFFF |................|

pronto 08:52:21

Figura 8 - arquivo dump do arquivo transferido
O comando de exibição exibirá o arquivo corretamente.

d pc1.txt

%phx_vos#m16_mas>SysAdmin>Noah_Davids>pc1.txt 10-09-05 08:54:25 mst

abcde

fghij

pronto 08:54:25

Figura 9 - exibição do arquivo transferido
Mas quando você for realmente ler o arquivo, o caractere de retorno da carruagem aparecerá no final de cada linha.
test_system_calls
tsc: s$attach_port p pc1.txt
tsc: s$open
tsc: s$seq_read p
Buffer length = 6
00000000 61626364 650D |abcde. |
tsc: s$seq_read p
Buffer length = 6
00000000 66676869 6A0D |fghij. |

tsc:

Figura 10 - caracteres de retorno de carruagem aparecem quando você lê o arquivo
Mais uma vez, o resultado é que o arquivo parece ser corrupto.
O seguinte script Perl pode ser usado para adicionar ou remover os caracteres de retorno do carro. Você deseja adicioná-los antes de transferir o arquivo para um sistema Microsoft Windows e removê-los depois de transferir o arquivo do sistema Microsoft Windows.
# cr.pl begins here
#
# cr
# version 1.0 10-08-27
# Noah.Davids@stratus.com
#
use strict;
use warnings;
use Getopt::Long;
my ($inFile, $outFile, @files, $add, $remove);
my ($INFILE);
my ($result, $count, $verbose, $addremove);
$result = GetOptions ('in=s' => $inFile,
'out=s' => $outFile,
'add' => $add,
'remove' => $remove,
'verbose=s' => $verbose);
if (($result != 1) || !defined ($inFile) || !defined ($outFile))
{
print "nnUsage:n";
print "perl cr.pl -in PATH -out PATH [[-add] | [-remove]] [-verbose]}n";
exit;
}
if (defined ($add) && defined ($remove))
{
print "You can only specify -add or -remove not bothnn";
print "nnUsage:n";
print "perl cr.pl -in PATH -out PATH [[-add] | [-remove]] [-verbose]}n";
exit;
}
@files = glob ($inFile);
if (@files < 1) {print "nNo files found for " . $inFile . "nn";}
if (@files > 1) {print "nMore than 1 file found for " . $inFile . "nn";}
open (OUT, ">".$outFile) || die "Can't open output file " . $outFile . "nn";
open ($INFILE, $files[0]) || die "Can't open input file " . $files[0] . "nn";
if (!defined ($verbose)) { $verbose = -1; }
$count = 0;
while ($_ = <$INFILE>)
{
if (defined ($remove))
{
s/r//;
print OUT $_ ;
}
else
{
s/n//;
print OUT $_ . "rn";
}
$count++;
if (($verbose > 0) && ($count % $verbose) == 0)
{ print "Line " . $count . " of " . $files[0] . " processedn"; }
}
close $INFILE;
#

# cr ends here

Figura 11 - Script perl para remover ou adicionar caracteres de retorno de carruagem
Por que o FTP parece funcionar? O FTP tem dois modos, ASCII e binário. No modo ASCII as transferências de um sistema Microsoft Windows para o OpenVOS resultam em um arquivo sequencial com os caracteres de retorno do carro e de alimentação de linha, ambos removidos dos registros. Transferências em modo binário do sistema Microsoft Windows para Open VOS resultam em um arquivo stream com os caracteres de retorno de carruagem e de alimentação de linha presentes - exatamente como a transferência em modo binário do SFTP. As transferências do modo ASCII do OpenVOS para um sistema Microsoft Windows resultam em um arquivo com os caracteres de retorno de carruagem e de alimentação de linha no final de cada linha, enquanto as transferências do modo binário resultam em um arquivo com apenas o caractere de alimentação de linha no final de cada linha. Novamente como a transferência em modo binário do SFTP. O RFC FTP entra em detalhes sobre como terminar linhas, mas o resultado final é que no modo ASCII tanto o cliente quanto o servidor são livres para terminar as linhas conforme necessário para o sistema operacional local enquanto no modo binário o cliente e o servidor não têm tal discrição.

© 2020 Stratus Technologies.