Ir al contenido principal

SFTP es el subsistema FTP que forma parte de SSH y permite realizar transferencias de archivos cifradas. Durante la última semana he tenido dos incidencias relacionadas con SFTP en las que los archivos no se transferían correctamente. En un caso, OpenVOS era el origen del archivo y, en el otro, OpenVOS era el destinatario. En ambos casos, los archivos contenían datos ASCII y los problemas tenían que ver con las diferencias entre cómo Microsoft Windows y OpenVOS terminan las líneas en un archivo de texto.

Empecemos con OpenVOS como punto de partida. Si creas un archivo de texto con tu editor favorito, estás creando un archivo secuencial. Por ejemplo:

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: visualización de un archivo de texto
El comando `display_file_status` muestra que se trata de un archivo secuencial y que, aunque el recuento de bytes de datos es de 10, en realidad el archivo contiene 20 bytes.
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 – Estado del archivo de visualización
El comando `dump_file` muestra la estructura real del archivo. Cada «línea» va precedida y terminada por dos bytes que indican su longitud. Estos bytes de longitud deben comenzar en un límite de bytes par, por lo que también hay un byte de relleno. Lo más importante que hay que tener en cuenta es que no hay caracteres típicos de fin de línea, ni un salto de línea (0x0A) ni una secuencia de retorno de carro y salto de línea (0x0D0A).
dump_file test%phx_vos#m16_mas>SysAdmin>Noah_Davids>prueba 05-09-10 08:14:07 mst
Número de bloque 1000  00053132 333435FF 00050005 36373839 |..12345…..6789|010 30FF0005 FFFFFFFF FFFFFFFF FFFFFFFF |0……………|020 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |…………….|

=

FF0 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |…………….|

Listo 08:14:07

Figura 3: archivo de volcado que muestra la estructura real del archivo

 

Cuando se transfiere el archivo mediante SFTP, OpenVOS elimina los bytes de longitud de la línea y añade un carácter de salto de línea. El resultado es que, mientras que el archivo original contenía 10 tipos de datos, el archivo transferido contiene 12.
C:Documents and SettingsnoahMy Documentstemp>"C:Program FilesPuTTYpsftp" [email protected]
Using username "nd".
[email protected]'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: La longitud del archivo transferido no coincide con la del archivo de origen
Además, si abres el archivo en un programa como el Bloc de notas, se muestra como una sola línea con símbolos extraños donde deberían terminar las líneas.
Figura 5: visualización del archivo en el Bloc de notas
Si utilizas una herramienta para obtener un volcado hexadecimal del archivo, verás que al final de cada línea hay un carácter de salto de línea (0x0A). La secuencia estándar de terminación de línea de Microsoft Windows es «retorno de carro y salto de línea» (0x0D0A); el Bloc de notas no sabe cómo interpretar únicamente el carácter de salto de línea, aunque hay otros editores que muestran el archivo correctamente.

 

Figura 6 – Volcado hexadecimal del archivo transferido
El resultado es que el archivo transferido parece estar dañado, tiene una longitud diferente y no se puede abrir, al menos en el Bloc de notas. Si conviertes el archivo a un formato de flujo antes de transferirlo, se solucionará el problema de la longitud; ambos archivos mostrarán ahora la misma longitud, pero el problema con el formato de las líneas seguirá sin resolverse.

 

¿Y qué ocurre si OpenVOS recibe un archivo de un sistema Microsoft Windows? Como ya he dicho, Microsoft Windows utiliza una secuencia de retorno de carro y avance de línea para terminar una línea.
Figura 7 – Volcado hexadecimal de un archivo creado en un sistema Microsoft Windows
El subsistema SFTP de OpenVOS creará un archivo de flujo. Los caracteres de salto de línea se interpretarán como caracteres de fin de línea, mientras que los caracteres de retorno de carro se tratarán como parte de los datos de la línea.

dump_file pc1.txt

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

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

010 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |…………….|

=

FF0 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |…………….|

Listo 08:52:21

Figura 8: archivo de volcado del archivo transferido
El comando «display» mostrará el archivo correctamente.

d pc1.txt

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

abcde

fghij

Listo 08:54:25

Figura 9: visualización del archivo transferido
Pero cuando vayas a leer el archivo, el carácter de retorno de carro aparecerá al final de cada línea.
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: al leer el archivo aparecen caracteres de retorno de carro
Una vez más, el resultado es que el archivo parece estar dañado.
El siguiente script de Perl se puede utilizar para añadir o eliminar los caracteres de retorno de carro. Es recomendable añadirlos antes de transferir el archivo a un sistema Microsoft Windows y eliminarlos después de transferirlo desde dicho sistema.
# cr.pl begins here
#
# cr
# version 1.0 10-08-27
#
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 en Perl para eliminar o añadir caracteres de retorno de carro
¿Por qué parece que el FTP funciona? El FTP tiene dos modos: ASCII y binario. En el modo ASCII, las transferencias desde un sistema Microsoft Windows a OpenVOS dan como resultado un archivo secuencial en el que se han eliminado de los registros tanto los caracteres de retorno de carro como los de avance de línea. Las transferencias en modo binario desde el sistema Microsoft Windows a OpenVOS dan como resultado un archivo de flujo en el que están presentes los caracteres de retorno de carro y avance de línea, exactamente igual que la transferencia en modo binario de SFTP. Las transferencias en modo ASCII desde OpenVOS a un sistema Microsoft Windows dan como resultado un archivo con caracteres de retorno de carro y avance de línea al final de cada línea, mientras que las transferencias en modo binario dan como resultado un archivo con solo el carácter de avance de línea al final de cada línea. De nuevo, igual que en la transferencia en modo binario de SFTP. El RFC de FTP detalla cómo terminar las líneas, pero la conclusión es que, en modo ASCII, tanto el cliente como el servidor tienen libertad para terminar las líneas según sea necesario para el sistema operativo local, mientras que en modo binario el cliente y el servidor no tienen esa discrecionalidad.