[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[FDclone-users:00349] Re: FDclone でファイルサイズが 0 と表示される
- Subject: [FDclone-users:00349] Re: FDclone でファイルサイズが 0 と表示される
- From: Takashi SHIRAI <shirai@unixusers.net>
- Date: Sat, 04 Dec 2004 06:01:02 +0900
しらいです。
In Message-Id <OF24DFE037.3592B272-ON49256F5F.0008038D@tky.lightwell.co.jp>
SHIOTA Shoichi <Shoichi.Shiota@lightwell.co.jp>さんwrites:
> 潮田です。
> もう一声足りないのは、 4GB over の方の表示です。
> 2GB over 同様 9 桁の 9 が表示されるのが仕様ですよね。
long long が存在しないと思って compile してしまっている訳
ですから、その前提に基づいて compile された結果、4GB 以上の
数値というのは扱えないんですよ。
そのため、64bit の off_t を 32bit の long に無理矢理 cast
した結果が表示されます。compiler の実装にも依存しますが、普
通だと下位 32bit だけ使われるんでしょうね。
> あれ、最下行はもっと長くないですか。
> いつも縦横とも広げた TeraTerm 越しに使用しているのでこの為かと、
> オリジナルの TeraTerm を default 状態で使用してみましたが、
ごめんなさい。桁上限を設けているのはオリジナル版『FD』の
画面レイアウトにした場合のサイズ表示でした。普通だと画面サイ
ズの許す限りの幅で表示しますね。
で、そっちの実装は「%u」でなく「%d」で受けてるので、正しく
表示されないんでしょう。
そもそも「%u」だと表示されるものが「%d」だとおかしくなると
いうのも妙な話なのでよくよく調べてみると、「%d」の場合符号拡
張する必要があるのでそこでミスっていたようです。
printf 関数呼出し側が渡した引数を、受け手側では一番大きい
型で受けている筈なのですが、long long が存在しないと思い込ん
でいる場合、32bit long で受けてしまいます。
実際は off_t は 64bit ある訳で、受ける変数の幅の方が小さい
ので、符号拡張しようとすると桁数の計算でおかしな計算を行なっ
てしまうようです。
具体的には負数分だけ算術シフトしようとして変な値を得ている
んでしょうね。負数分の算術シフトはどうも実装依存のようで、他
の環境ではなかなか再現しませんでした。
> 対応が面倒(困難)なら、 HAVELONGLONG を入れる方の対応で良いのでは
> ないかと思いはじめました。
HAVELONGLONG は AIX に共通項目でない限り無闇に使えませんし、
他にも long long の存在を認識出来ない環境があるかも知れない
ので、上記の 4GB 以上は諦めるとしてもそれ以内は何とかしたい
ところですよね。
という訳で、HAVELONGLONG が自動検出出来ない環境用の patch
です。
---- Cut Here ----
diff -u ../old/FD-2.06a/printf.c ./printf.c
--- ../old/FD-2.06a/printf.c Wed Sep 8 00:00:00 2004
+++ ./printf.c Sat Dec 4 05:34:29 2004
@@ -175,10 +175,7 @@
}
else if (n >= 0) sign = (pbufp -> flags & VF_PLUS) ? 1 : 0;
#endif /* !MINIMUMSHELL */
- else {
- sign = -1;
- n = -n;
- }
+ else sign = -1;
#ifdef MINIMUMSHELL
if (sign) width--;
@@ -193,11 +190,18 @@
}
else while (len < sizeof(num) / sizeof(char)) {
#ifdef MINIMUMSHELL
- if (!bit) i = (n % base) + '0';
+ if (!bit) {
+ i = (n % base);
+ if (i < 0) i = -i;
+ i += '0';
+ }
else if ((i = (u & base)) < 10) i += '0';
#else
- if (!bit) i = '0'
- + (((pbufp -> flags & VF_UNSIGNED) ? u : n) % base);
+ if (!bit) {
+ if (pbufp -> flags & VF_UNSIGNED) i = u % base;
+ else if ((i = n % base) < 0) i = -i;
+ i += '0';
+ }
else if ((i = (u & base)) < 10) i += '0';
else if (cap) i += 'A' - 10;
else i += 'a' - 10;
@@ -495,6 +499,40 @@
#endif
else u = va_arg(args, u_int);
+#ifndef HAVELONGLONG
+ if (len > sizeof(long_t)) {
+ u_long_t hi, tmp;
+
+ while (len > sizeof(long_t)) {
+ hi = va_arg(args, long_t);
+ len -= sizeof(long_t);
+ }
+
+ tmp = 0x5a;
+ cp = (char *)(&tmp);
+ if (*cp != 0x5a) {
+ tmp = hi;
+ hi = u;
+ u = tmp;
+ }
+
+ if (pbufp -> flags & VF_UNSIGNED) {
+ if (hi) u = MAXUTYPE(u_long_t);
+ }
+ else {
+ mask = (MAXUTYPE(u_long_t) >> 1);
+ if (hi & ~mask) {
+ if (++hi || !(u & ~mask))
+ u = ~mask;
+ }
+ else {
+ if (hi || (u & ~mask))
+ u = mask;
+ }
+ }
+ }
+ else
+#endif /* !HAVELONGLONG */
if (!(pbufp -> flags & VF_UNSIGNED)) {
mask = (MAXUTYPE(u_long_t)
>> ((sizeof(long_t) - len)
---- Cut Here ----
ちゃんと上位 32bit の符号を見て、符号拡張の逆を行なうよう
にしました。その結果 MAXLONG や MINLONG を越えてしまった場合
には MAXLONG や MINLONG の値に丸めるようにしてあります。
patch の前半は、実は実装をサボって -MAXLONG〜MAXLONG の範
囲しか表示出来ない仕様だったのを、ちゃんと MINLONG まで表示
させるようにしただけです。
こんな感じで取り敢えずは凌げるんじゃないでしょうか?
しらい たかし