niXforums Forum Index
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   PreferencesPreferences   Log in to check your private messagesLog in to check your private messages   Log inLog in 
·  nixdoc.net ·  man pages ·  Linux HOWTOs ·  FreeBSD Tips ·  Forums
navigation Forum index » *nix » BSD » FreeBSD » mail-lists » Architecture
getbsize(3): Convert blocksizep to be unsigned long?
Post new topic   Reply to topic Page 1 of 1 [2 Posts] View previous topic :: View next topic
Author Message
Xin LI
*nix forums beginner


Joined: 09 Nov 2004
Posts: 44

PostPosted: Tue Jun 06, 2006 1:35 am    Post subject: getbsize(3): Convert blocksizep to be unsigned long? Reply with quote

Dear folks,

When I was twiddling df(1)'s code I found that getbsize(3) accepts
blocksizep as long *. Because that the manual page says:

"The memory referenced by blocksizep is filled in with block size, in
bytes."

I think it makes no sense for the number to be negative. Is it
reasonable to apply the attached patch?

Cheers,
--
Xin LI <delphij delphij net> http://www.delphij.net/
Back to top
Bruce Evans
*nix forums Guru Wannabe


Joined: 22 Mar 2002
Posts: 190

PostPosted: Wed Jun 07, 2006 12:41 am    Post subject: Re: getbsize(3): Convert blocksizep to be unsigned long? Reply with quote

On Tue, 6 Jun 2006, Xin LI wrote:

Quote:
When I was twiddling df(1)'s code I found that getbsize(3) accepts
blocksizep as long *. Because that the manual page says:

"The memory referenced by blocksizep is filled in with block size, in
bytes."

I think it makes no sense for the number to be negative. Is it
reasonable to apply the attached patch?

No. This mistake has been committed and backed out once too often
already (in 2002). The previous interface chance was from "long *"
to "size_t *". This was a larger change since it also increased the
size of the pointed-to object on 64-bit machines, thus changing the
ABI very unnecessarily.

Using unsigned values gives sign extension bugs and breaks overflow
checks that can be done in principle for sign values but not unsigned
ones. df and statfs() are good examples of the sign extension bugs.
statfs() used to supply correctly signed types (i.e., only signed
ones), and naive users of statfs() like df still depend on this, but
statfs() now supplies a mixture of signed and unsigned types, giving
sign extension bugs or requiring lots of casts to avoid them when the
types are mixed or unsigned values are subtracted. getbsize() still
supports a correctly signed type.

I use the following fix for the type error in df.c:

%%%
Index: df.c
===================================================================
RCS file: /home/ncvs/src/bin/df/df.c,v
retrieving revision 1.62
diff -u -2 -r1.62 df.c
--- df.c 4 Jun 2004 09:30:51 -0000 1.62
+++ df.c 4 Jun 2004 10:15:16 -0000
@@ -363,13 +364,14 @@
prtstat(struct statfs *sfsp, struct maxwidths *mwp)
{
- static u_long blocksize;
- static int headerlen, timesthrough = 0;
- static const char *header;
- int64_t used, availblks, inodes;
+ static long blocksize;
+ static int timesthrough;
+ const char *header;
+ int64_t availblks, inodes, used;
+ int headerlen;

if (++timesthrough == 1) {
mwp->mntfrom = imax(mwp->mntfrom, (int)strlen("Filesystem"));
if (hflag) {
- header = " Size";
+ header = " Size";
mwp->total = mwp->used = mwp->avail =
(int)strlen(header);
@@ -440,5 +442,5 @@
update_maxwidths(struct maxwidths *mwp, const struct statfs *sfsp)
{
- static u_long blocksize = 0;
+ static long blocksize;
int dummy;

%%%

The patch also fixes some style bugs and has part of a fix for a bug
in the output formatting.

"long blocksize" is now passed to fsbtoblk() which expects "u_long
bs". The interface to fsbtoblk() should be changed too, but there is
no actual problem due to the block size easily fitting in a signed
long and fsbtoblk() defending against sign botches internally:

% static intmax_t
% fsbtoblk(int64_t num, uint64_t fsbs, u_long bs)
% {
%
% if (fsbs != 0 && fsbs < bs)
% return (num / (intmax_t)(bs / fsbs));
% else
% return (num * (intmax_t)(fsbs / bs));
% }

Note that `num' needs to be signed here since negative block counts can
happen for f_bavail, and it is actually signed. It also needs to be
divided by a signed value (with a positive sign) so that it doesn't
get promoted to a huge unsigned value when numerator is a small signed
value and the type of the denominator is unsigned and longer than the
type of the numerator. This was broken in rev.1.52 when the type of
fsbs (f_bsize in struct statfs) was broken from long to uint64_t.
Rev.1.52 also broken type type for bs (blocksize) from long to u_long,
but since u_long is smaller than uint64_t on all supported arches,
this made no additional difference to the type pf (bs / fsbs) or
(fsbsd / bss) -- that type is always uint64_t. Rev.1.56 works around
these sign extension bugs by casting the denominator to int64_t.

Rev.1.62 cleans up or down the interface of fsbtoblk() a little. Before
rev.1.52, was a macro that operated only on signed types and just worked.
Macros can work on "any" types provided that they don't mix unsigned
types with signed ones and/or don't overflow. Overflow is avoided
by not doing the multiplication (num * fsbs) first. Even this overflow
avoidance is now bogus, since off_t has the same size as the block counts
(all are 64 bits) so overflow can only occur if the args are garbage,
so fsbtoblk() could be the even simpler macro:

#define fsbtoblk(num, fsbs, bs) ((num) * (fsbs) / (bs))

provided there are no sign extension botches (the block sizes must be
signed if num is signed). Casting things to signed types to avoid the
sign extension bugs is worse than using signed types throughout, since it
is uglier and strictly needs overflow checks for every conversion (cases
where the extra bit provided by unsigned types is actually needed might
cause overflow), and would require adding casts to interfaces that could
be type-generic modulo signedness, and would generate larger code (see the
commit log to rev.1.62). OTOH, casting everything to floating point would
work well -- everything would become signed, integral values up to about
2^53 would be represented exactly, and larger values would never cause
overflow and would be represented exactly enough.

Befor
_______________________________________________
freebsd-arch@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-arch
To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"
Back to top
Google

Back to top
Display posts from previous:   
Post new topic   Reply to topic Page 1 of 1 [2 Posts] View previous topic :: View next topic
The time now is Tue Dec 02, 2008 3:17 pm | All times are GMT
navigation Forum index » *nix » BSD » FreeBSD » mail-lists » Architecture
Jump to:  

Similar Topics
Topic Author Forum Replies Last Post
No new posts Need to convert domain name before relaying jfinn Postfix 0 Tue Sep 16, 2008 12:51 pm
No new posts how to convert byte array into integer msosno01@gmail.com C++ 3 Thu Jul 20, 2006 9:07 pm
No new posts how to convert byte array into integer msosno01@gmail.com C++ 1 Thu Jul 20, 2006 9:01 pm
No new posts blocking mails with long lines and giberish Dale Blount Postfix 4 Thu Jul 20, 2006 2:31 pm
No new posts long path names for ifstream in( Fred J. C++ 1 Thu Jul 20, 2006 2:06 am

MPAA | Ringtones | Mortgage Calculator | Online Advertising | Herbal Supplements
Copyright © 2004-2005 DeniX Solutions SRL
 
Other DeniX Solutions sites: Unix/Linux blog |  electronics forum |  medicine forum |  science forum | 
Privacy Policy


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.2155s ][ Queries: 16 (0.1331s) ][ GZIP on - Debug on ]