Zum Hauptinhalt springen

SFTP ist das FTP-Subsystem, das Teil von SSH ist und Ihnen verschlüsselte Dateiübertragungen ermöglicht. In der vergangenen Woche hatte ich zwei Probleme mit SFTP, bei denen Dateien nicht ordnungsgemäß übertragen wurden. In einem Fall war OpenVOS die Quelle der Datei, im anderen Fall empfing OpenVOS die Datei. In beiden Fällen enthielten die Dateien ASCII-Daten, und die Probleme hingen mit den Unterschieden zwischen Microsoft Windows und OpenVOS bei der Zeilenbeendigung in Textdateien zusammen.

Beginnen wir mit OpenVOS als Quelle. Wenn Sie mit Ihrem bevorzugten Editor eine Textdatei erstellen, erstellen Sie eine sequenzielle Datei. Zum Beispiel

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

ready 08:13:49

Abbildung 1 – Anzeige einer Textdatei
Der Befehl display_file_status zeigt, dass es sich um eine sequentielle Datei handelt und dass die Datenbyteanzahl zwar 10 beträgt, die Datei jedoch tatsächlich 20 Bytes enthält.
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

Abbildung 2 – Status von display_file
Der Befehl dump_file zeigt die tatsächliche Struktur der Datei an. Jeder „Zeile“ gehen zwei Bytes voraus und folgen zwei Bytes, die ihre Länge angeben. Diese Längenbytes müssen an einer geraden Byte-Grenze beginnen, daher gibt es auch ein Füllbyte. Bemerkenswert ist, dass es keine typischen Zeilenendezeichen gibt, weder eine Zeilenvorschubsequenz (0x0A) noch eine Wagenrücklauf-Zeilenvorschubsequenz (0x0D0A).
dump_file test%phx_vos#m16_mas>SysAdmin>Noah_Davids>test 05.09.2010, 08:14:07 Uhr (MST)
Blocknummer 1000  00053132 333435FF 00050005 36373839 |..12345…..6789|010 30FF0005 FFFFFFFF FFFFFFFF FFFFFFFF |0……………|020 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |…………….|

=

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

bereit 08:14:07

Abbildung 3 – dump_file zeigt die tatsächliche Struktur der Datei

 

Wenn Sie die Datei mit SFTP übertragen, entfernt OpenVOS die Längenbytes aus der Zeile und fügt ein Zeilenvorschubzeichen hinzu. Das Ergebnis ist, dass die ursprüngliche Datei 10 Datentypen enthielt, die übertragene Datei jedoch 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
Abbildung 4 – Die Länge der übertragenen Datei stimmt nicht mit der Länge der Quelldatei überein.
Wenn Sie die Datei in einem Programm wie Notepad anzeigen, wird sie als eine Zeile mit seltsamen Symbolen angezeigt, wo die Zeilen enden sollten.
Abbildung 5 – Anzeige der Datei im Notepad
Wenn Sie ein Dienstprogramm verwenden, um einen Hex-Dump der Datei zu erhalten, werden Sie feststellen, dass am Ende jeder Zeile ein Zeilenvorschubzeichen (0x0A) steht. Die Standard-Zeilenendezeichenfolge von Microsoft Windows ist Wagenrücklauf-Zeilenvorschub (0x0D0A). Notepad kann das Zeilenvorschubzeichen nicht interpretieren, obwohl es andere Editoren gibt, die die Datei korrekt anzeigen.

 

Abbildung 6 – Hex-Dump der übertragenen Datei
Das Ergebnis ist, dass die übertragene Datei beschädigt zu sein scheint, die Länge unterschiedlich ist und Sie sie nicht anzeigen können – zumindest nicht im Notepad. Durch Konvertieren der Datei in eine Stream-Datei vor der Übertragung wird das Längenproblem behoben; beide Dateien weisen nun die gleiche Länge auf, aber das Problem mit den Zeilenenden bleibt bestehen.

 

Was passiert nun, wenn OpenVOS eine Datei von einem Microsoft Windows-System empfängt? Wie bereits erwähnt, verwendet Microsoft Windows eine Zeilenumbruch-Zeilenvorschub-Sequenz, um eine Zeile zu beenden.
Abbildung 7 – Hex-Dump einer auf einem Microsoft Windows-System erstellten Datei
Das OpenVOS-SFTP-Subsystem erstellt eine Stream-Datei. Die Zeilenvorschubzeichen werden als Zeilenendezeichen interpretiert, während die Wagenrücklaufzeichen als Teil der Zeilendaten behandelt werden.

dump_file pc1.txt

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

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

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

=

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

bereit 08:52:21

Abbildung 8 – Dump-Datei der übertragenen Datei
Der Befehl „display“ zeigt die Datei korrekt an.

d pc1.txt

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

abcde

fghij

bereit 08:54:25

Abbildung 9 – Anzeige der übertragenen Datei
Wenn Sie jedoch die Datei tatsächlich lesen, wird am Ende jeder Zeile das Wagenrücklaufzeichen angezeigt.
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:

Abbildung 10 – Wagenrücklaufzeichen werden angezeigt, wenn Sie die Datei lesen.
Auch hier ist das Ergebnis, dass die Datei beschädigt zu sein scheint.
Das folgende Perl-Skript kann zum Hinzufügen oder Entfernen der Wagenrücklaufzeichen verwendet werden. Sie sollten diese Zeichen vor der Übertragung der Datei auf ein Microsoft Windows-System hinzufügen und nach der Übertragung der Datei vom Microsoft Windows-System entfernen.
# 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

Abbildung 11 – Perl-Skript zum Entfernen oder Hinzufügen von Wagenrücklaufzeichen
Warum scheint FTP zu funktionieren? FTP verfügt über zwei Modi: ASCII und Binär. Im ASCII-Modus führt die Übertragung von einem Microsoft Windows-System zu OpenVOS zu einer sequenziellen Datei, in der die Zeichen für Wagenrücklauf und Zeilenvorschub aus den Datensätzen entfernt wurden. Übertragungen im Binärmodus vom Microsoft Windows-System zu Open VOS führen zu einer Stream-Datei, in der die Zeichen für Wagenrücklauf und Zeilenvorschub vorhanden sind – genau wie bei der Übertragung im Binärmodus von SFTP. Übertragungen im ASCII-Modus von OpenVOS zu einem Microsoft Windows-System führen zu einer Datei mit Wagenrücklauf- und Zeilenvorschubzeichen am Ende jeder Zeile, während Übertragungen im Binärmodus zu einer Datei führen, in der nur das Zeilenvorschubzeichen am Ende jeder Zeile vorhanden ist. Auch dies entspricht der Übertragung im Binärmodus von SFTP. Der FTP-RFC geht detailliert auf die Beendigung von Zeilen ein, aber unterm Strich können im ASCII-Modus sowohl Client als auch Server die Zeilen nach Bedarf für das lokale Betriebssystem beenden, während Client und Server im Binärmodus keine solche Entscheidungsfreiheit haben.