メインコンテンツへスキップ
検索

SFTPはSSHの一部であるFTPサブシステムで、暗号化されたファイル転送を行うことができます。この1週間で、SFTPが正しくファイルを転送しないという問題が2件発生しました。1つはOpenVOSがファイルのソースで、もう1つはOpenVOSがファイルを受信するケースでした。どちらの場合も、ファイルにはASCIIデータが含まれており、問題は、MicrosoftWindows とOpenVOSがテキストファイルの行を終了する方法の違いに関係しています。

まずはOpenVOSをソースにしてみましょう。好きなエディタを使ってテキストファイルを作成すると、シーケンシャルファイルになります。例えば

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

ready 08:13:49

図1-テキストファイルの表示
display_file_statusコマンドを実行すると、シーケンシャルファイルであること、データバイト数が10であるのに対し、実際には20バイトあることがわかります。
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

図2 - display_file の状態
dump_fileコマンドは,ファイルの実際の構造を表示する。各「行」の前後には、長さを示す2バイトが置かれます。これらの長さバイトは、偶数バイトの境界で開始しなければならないため、フィラーバイトもあります。注目すべき点は、典型的な行終端文字であるラインフィード(0x0A)またはキャリッジリターン・ラインフィード(0x0D0A)のシーケンスがないことです。
dump_file test%phx_vos#m16_mas>SysAdmin>Noah_Davids>test 10-09-05 08:14:07 mst
ブロック番号1000  00053132 333435FF 00050005 36373839 |..12345…..6789|010 30FF0005 FFFFFF FFFFFF FFFFFF |0...............|020 FFFFFF FFFFFF FFFFFF FFFFFF |................|

=

FF0 FFFFFF FFFFFF FFFFFF|................|。

準備完了 08:14:07

図3 - ファイルの実際の構造を示すdump_file

 

SFTPでファイルを転送すると、OpenVOSは行から長さのバイトを取り除き、改行文字を付加します。その結果、元のファイルには10種類のデータタイプが含まれていたのに対し、転送されたファイルには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
図4 - 転送されたファイルの長さと転送元のファイルの長さが一致しない
さらに、このファイルをメモ帳などで表示すると、1行で表示され、行末にはおかしな記号が表示されます。
図5-メモ帳でのファイルの表示
ユーティリティを使ってファイルの16進ダンプを取ると、各行の終わりに改行文字(0x0A)があることがわかります。Windows Microsoftの標準的な行終端シーケンスはキャリッジリターン・ラインフィード(0x0D0A)です。メモ帳はラインフィード文字だけを解釈する方法を知らないのですが、ファイルを正しく表示するエディターは他にもあります。

 

図6 - 転送されたファイルのHexダンプ
その結果、転送されたファイルは破損しているように見え、長さが異なり、少なくともメモ帳では表示できませんでした。ファイルをストリームファイルに変換してから転送すると、長さの問題は修正されます。両方のファイルの長さは同じになりますが、行末の問題は残ります。

 

さて、OpenVOSがMicrosoftWindows Systemからファイルを受信している場合はどうでしょうか。すでに述べたように、MicrosoftWindows は行の終了にキャリッジリターン・ラインフィードシーケンスを使用します。
図7 - MicrosoftWindows システムで作成されたファイルのヘキサダンプ
OpenVOSのSFTPサブシステムは、ストリームファイルを作成します。改行文字は行末文字として、キャリッジリターン文字は行のデータの一部として扱われます。

dump_file pc1.txt

%phx_vos#m16_mas>SysAdmin>Noah_Davids>pc1.txt 10-09-05 08:52:21 MST
ブロック番号1

000 61626364650D0A66 6768696A0D0AFFFF|abcde..fghij....|

010 FFFFFF FFFFFF FFFFFF |................|

=

FF0 FFFFFF FFFFFF FFFFFF|................|。

準備完了 08:52:21

図8 - 転送されたファイルのダンプファイル
displayコマンドでファイルが正しく表示されます。

d pc1.txt

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

abcde

fghij

準備完了 08:54:25

図9 - 転送されたファイルの表示
しかし、実際にファイルを読もうとすると、キャリッジリターン文字が各行の最後に表示されます。
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:

図10 - ファイルを読むとキャリッジリターン文字が表示される
この場合も、「ファイルが壊れているようです」という結果になります。
以下のPerlスクリプトを使用すると、キャリッジリターン文字を追加または削除することができます。MicrosoftWindows システムにファイルを転送する前に追加し、MicrosoftWindows システムからファイルを転送した後に削除したい場合です。
# 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

図11 - キャリッジリターン文字を削除または追加するPerlスクリプト
なぜFTPは動作するように見えるのですか?FTP には、ASCII とバイナリの 2 つのモードがあります。ASCIIモードでは、MicrosoftWindows システムからOpenVOSへの転送は、キャリッジリターンとラインフィード文字が両方ともレコードから削除されたシーケンシャルなファイルになります。バイナリモードでは、MicrosoftWindows システムから Open VOS への転送は、キャリッジリターンとラインフィード文字が存在するストリームファイルになります - SFTP のバイナリモード転送とまったく同じです。OpenVOS から MicrosoftWindows システムへの ASCII モード転送では、各行の終わりにキャリッジリターンとラインフィード文字があるファイルになりますが、バイナリモード転送では、各行の終わりにラインフィード文字があるだけのファイルになります。これもSFTPのバイナリモード転送と同じです。FTP RFCでは、行の終了方法について詳しく説明していますが、要するに、ASCIIモードではクライアントとサーバーの両方がローカルのオペレーティングシステムに必要な行を自由に終了できるのに対し、バイナリモードではクライアントとサーバーにそのような裁量権はないということです。
メニューを閉じる

© 2020ストラタステクノロジー.