[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[FDclone-users:00495] Re: FDclone でファイルサイズが 0 と表示される
- Subject: [FDclone-users:00495] Re: FDclone でファイルサイズが 0 と表示される
- From: Takashi SHIRAI <shirai@unixusers.net>
- Date: Fri, 14 Apr 2006 02:04:15 +0900
しらいです。
随分前の記事ですが...。
In Message-Id <20041203210102.F26AE40C417@yuka.unixusers.net>
Takashi SHIRAI <shirai@unixusers.net>writes:
> しらいです。
> printf 関数呼出し側が渡した引数を、受け手側では一番大きい
> 型で受けている筈なのですが、long long が存在しないと思い込ん
> でいる場合、32bit long で受けてしまいます。
> 実際は off_t は 64bit ある訳で、受ける変数の幅の方が小さい
> ので、符号拡張しようとすると桁数の計算でおかしな計算を行なっ
> てしまうようです。
> 具体的には負数分だけ算術シフトしようとして変な値を得ている
> んでしょうね。負数分の算術シフトはどうも実装依存のようで、他
> の環境ではなかなか再現しませんでした。
この時に printf() 側の対応を行なったのですが、同様のことが
sscanf() 側でも言えて、そっちの対応を怠っていました。
なので、long long を使えない環境、具体的には AIX なんです
が、そういうケースではアーカイブファイルの中身を覗いた時に全
てのファイルサイズが 0 になってしまっていました。
この対応をし、更に printf() 側ももう少し丁寧に対応し直しま
したので、AIX 環境をお持ちの方は以下の patch を試してみて頂
けないでしょうか。
---- Cut Here ----
diff -u ../old/FD-2.08b/parse.c ./parse.c
--- ../old/FD-2.08b/parse.c Thu Mar 30 00:00:00 2006
+++ ./parse.c Fri Apr 14 01:36:45 2006
@@ -274,6 +274,27 @@
memcpy(&u, &n, sizeof(u));
}
+#ifndef HAVELONGLONG
+ if (len > (int)sizeof(u_long_t)) {
+ char *buf;
+ u_long_t tmp;
+ int hi;
+
+ hi = 0;
+ if (!(flags & VF_UNSIGNED)) {
+ mask = (MAXUTYPE(u_long_t) >> 1);
+ if (u & ~mask) hi = 0xff;
+ }
+ buf = va_arg(args, char *);
+ memset(buf, hi, len);
+
+ tmp = 0x5a;
+ cp = (char *)(&tmp);
+ if (*cp != 0x5a) buf += len - sizeof(u_long_t);
+ memcpy(buf, (char *)(&u), sizeof(u));
+ }
+ else
+#endif /* !HAVELONGLONG */
if (len == (int)sizeof(u_long_t))
*(va_arg(args, u_long_t *)) = u;
#ifdef HAVELONGLONG
diff -u ../old/FD-2.08b/printf.c ./printf.c
--- ../old/FD-2.08b/printf.c Thu Mar 30 00:00:00 2006
+++ ./printf.c Fri Apr 14 01:48:28 2006
@@ -496,29 +496,37 @@
}
if (base) {
- if (len == (int)sizeof(u_long_t))
- u = va_arg(args, u_long_t);
-#ifdef HAVELONGLONG
- else if (len == (int)sizeof(u_long))
- u = va_arg(args, u_long);
-#endif
- else u = va_arg(args, u_int);
-
#ifndef HAVELONGLONG
if (len > (int)sizeof(u_long_t)) {
- u_long_t hi, tmp;
-
- while (len > (int)sizeof(u_int)) {
- hi = va_arg(args, u_int);
- len -= (int)sizeof(u_int);
- }
+ u_long_t tmp;
+ int hi;
+# ifndef HPUX
+ /*
+ * HP-UX always pushes arguments from lowest to uppermost,
+ * in spite of the CPU endien.
+ */
tmp = 0x5a;
cp = (char *)(&tmp);
if (*cp != 0x5a) {
- tmp = hi;
- hi = u;
- u = tmp;
+ hi = va_arg(args, u_int);
+ len -= (int)sizeof(u_int);
+ while (len > (int)sizeof(u_long_t)) {
+ tmp = va_arg(args, u_int);
+ len -= (int)sizeof(u_int);
+ }
+ u = va_arg(args, u_long_t);
+ }
+ else
+# endif /* !HPUX */
+ {
+ hi = 0;
+ u = va_arg(args, u_long_t);
+ len -= (int)sizeof(u_long_t);
+ while (len > 0) {
+ hi = va_arg(args, u_int);
+ len -= (int)sizeof(u_int);
+ }
}
if (pbufp -> flags & VF_UNSIGNED) {
@@ -526,7 +534,7 @@
}
else {
mask = (MAXUTYPE(u_long_t) >> 1);
- if (hi & ~mask) {
+ if (hi < 0) {
if (++hi || !(u & ~mask))
u = ~mask;
}
@@ -538,6 +546,18 @@
}
else
#endif /* !HAVELONGLONG */
+ if (len == (int)sizeof(u_long_t))
+ u = va_arg(args, u_long_t);
+#ifdef HAVELONGLONG
+ else if (len == (int)sizeof(u_long))
+ u = va_arg(args, u_long);
+#endif
+ else u = va_arg(args, u_int);
+
+#ifndef HAVELONGLONG
+ if (len > (int)sizeof(u_long_t)) /*EMPTY*/;
+ else
+#endif
if (!(pbufp -> flags & VF_UNSIGNED)) {
mask = (MAXUTYPE(u_long_t)
>> (((int)sizeof(long_t) - len)
---- Cut Here ----
> HAVELONGLONG は AIX に共通項目でない限り無闇に使えませんし、
少なくとも AIX 4.1 以降では long long は使えているようなの
で、_AIX41 が pre-define されていれば HAVELONGLONG を定義し
ても構わないような気がしてきました。
しらい たかし