Passa al contenuto principale

SFTP è il sottosistema FTP che fa parte di SSH, permette di fare trasferimenti di file criptati. Nell'ultima settimana ho avuto 2 problemi con SFTP che non trasferiva correttamente i file. In un caso OpenVOS era la fonte del file e nell'altro caso OpenVOS stava ricevendo il file. In entrambi i casi i file contenevano dati ASCII e i problemi avevano a che fare con le differenze tra il modo in cui Microsoft Windows e OpenVOS terminano le linee in un file di testo.

Cominciamo con OpenVOS come sorgente. Se si crea un file di testo usando il proprio editor preferito si crea un file sequenziale. Per esempio

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 - visualizzazione di un file di testo
Il comando display_file_status mostra che si tratta di un file sequenziale e che mentre il conteggio dei byte dei dati è 10 ci sono effettivamente 20 byte nel file.
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 - stato di display_file
Il comando dump_file mostra la struttura reale del file. Ogni "linea" è preceduta e terminata da 2 byte che indicano la sua lunghezza. Questi byte di lunghezza devono iniziare su un confine di byte pari, quindi c'è anche un byte di riempimento. La cosa significativa da notare è che non ci sono i tipici caratteri di fine linea, né una sequenza di avanzamento linea (0x0A) né una sequenza di ritorno a capo (0x0D0A).
dump_file test%phx_vos#m16_mas>SysAdmin>Noah_Davids>test 10-09-05 08:14:07 mst
Blocco numero 1000  00053132 333435FF 00050005 36373839 |..12345…..6789|010 30FF0005 FFFFFFFF FFFFFFFF FFFFFFFF |0...............|020 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|

=

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

pronto 08:14:07

Figura 3 - dump_file che mostra la struttura attuale del file

 

Quando si trasferisce il file usando SFTP, OpenVOS toglie i byte di lunghezza dalla linea e aggiunge un carattere di avanzamento linea. Il risultato è che mentre il file originale conteneva 10 tipi di dati, il file trasferito ne 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 lunghezza del file trasferito non corrisponde alla lunghezza del file sorgente
Inoltre, se si visualizza il file in qualcosa come Notepad, viene visualizzato come una sola linea con strani simboli dove le linee dovrebbero terminare.
Figura 5 - visualizzazione del file in Notepad
Se usi un'utility per ottenere un dump esadecimale del file vedrai che alla fine di ogni riga c'è un carattere di avanzamento linea (0x0A). La sequenza standard di terminazione di linea di Microsoft Windows è il ritorno a capo (0x0D0A), Notepad non sa interpretare solo il carattere di avanzamento di linea, anche se ci sono altri editor che visualizzeranno il file correttamente.

 

Figura 6 - Hex dump del file trasferito
Il risultato è che il file trasferito sembra essere corrotto, la lunghezza è diversa e non puoi visualizzarlo - almeno in Notepad. Convertire il file in un file di flusso prima di trasferirlo correggerà il problema della lunghezza; entrambi i file mostreranno ora la stessa lunghezza ma il problema della terminazione delle linee rimarrà.

 

Ora, cosa succede se OpenVOS riceve un file da un sistema Microsoft Windows? Come ho già detto, Microsoft Windows usa una sequenza di ritorno a capo per terminare una linea.
Figura 7 - Hex dump di un file creato su un sistema Microsoft Windows
Il sottosistema SFTP di OpenVOS creerà un file di flusso. I caratteri di avanzamento linea saranno presi come caratteri di fine linea e i caratteri di ritorno a capo saranno trattati come parte dei dati della linea.

dump_file pc1.txt

%phx_vos#m16_mas>SysAdmin>Noah_Davids>pc1.txt 10-09-05 08:52:21 mst
Blocco numero 1

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

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

=

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

pronto 08:52:21

Figura 8 - file dump del file trasferito
Il comando display visualizzerà correttamente il file.

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 - visualizzazione del file trasferito
Ma quando si va a leggere il file, il carattere di ritorno a capo appare alla fine di ogni riga.
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 - i caratteri di ritorno a capo appaiono quando si legge il file
Di nuovo, il risultato è che il file sembra essere corrotto.
Il seguente script Perl può essere usato per aggiungere o rimuovere i caratteri di ritorno a capo. Si desidera aggiungerli prima di trasferire il file a un sistema Microsoft Windows e rimuoverli dopo aver trasferito il file dal sistema Microsoft Windows.
# 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 Perl per rimuovere o aggiungere caratteri di ritorno a capo
Perché FTP sembra funzionare? FTP ha due modalità, ASCII e binaria. In modalità ASCII i trasferimenti da un sistema Microsoft Windows a OpenVOS risultano in un file sequenziale con i caratteri di ritorno a capo e di avanzamento linea rimossi dai record. I trasferimenti in modalità binaria dal sistema Microsoft Windows a Open VOS risultano in un file di flusso con i caratteri di ritorno a capo e di avanzamento linea presenti - esattamente come il trasferimento in modalità binaria di SFTP. I trasferimenti in modalità ASCII da OpenVOS a un sistema Microsoft Windows risultano in un file con i caratteri di ritorno a capo e di avanzamento linea alla fine di ogni linea, mentre i trasferimenti in modalità binaria risultano in un file con solo il carattere di avanzamento linea alla fine di ogni linea. Di nuovo proprio come il trasferimento in modalità binaria di SFTP. L'FTP RFC entra in dettaglio su come terminare le linee ma la linea di fondo è che in modalità ASCII sia il client che il server sono liberi di terminare le linee come necessario per il sistema operativo locale mentre in modalità binaria client e server non hanno tale discrezione.

© 2024 Stratus Technologies.