[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[FDclone-users:00495] Re: FDclone でファイルサイズが 0 と表示される



 しらいです。

 随分前の記事ですが...。

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 を定義し
ても構わないような気がしてきました。

                                               しらい たかし