Re: max file size (again)...

From: Wietse Venema (no email)
Date: Mon Sep 01 2003 - 20:41:36 EDT


Following up to my own posting, perhaps we have a portable
solution after all.

Wietse Venema:
> Postfix must be able to seek files, therefore files can't be larger
> than the largest off_t value. What should Postfix do when the
> system imposed file size limit is larger than what can be represented
> as a file offset? The best is to truncate the limit to the largest
> positive off_t value.
>
> It seems relatively safe to assume that off_t is a signed integer
> type in two's complement format. What is the portable way to find
> out the largest value of such a signed integer?
>
> Coming back to your proposed macro:
>
> #define FSIZE_MAX (off_t)1<<((sizeof(off_t)*8)-1)
>
> This macro assumes that bytes are 8 bits wide, but the C standard
> does not require this. Postfix runs on machines other than peecees
> and I would not like to lose those platforms. Fortunately, ANSI C
> defines the CHAR_BIT constant in <limits.h> for this exact purpose.
>
> So let's fix this portability problem. While we're at it, let's
> also fix a potential operator precedence problem by adding add
> outer parentheses. And let's generalize this macro a bit so that
> it can be tested easily.
>
> #define MAX_POSITIVE_OF(T) ((T) 1 << ((sizeof(T) * CHAR_BIT) - 1))
>
> This reveals that the original macro has bigger problems than 8-bit
> byte assumptions or operator precedence conflicts. The macro simply
> computes the wrong result.
>
> For example,
>
> MAX_POSITIVE_OF(char) evaluates to 128, should be 127
> MAX_POSITIVE_OF(short) evaluates to 32768, should be 32767

Here's something that appears to work better:

    #include <sys/types.h>
    #include <limits.h>
    #include <stdio.h>

    #define MAXINT(T) ((T) (((T)1 << ((sizeof(T) * CHAR_BIT) - 1) ^ ((T) -1))))

    main()
    {
        printf("%d\n", MAXINT(char));
        printf("%d\n", MAXINT(short));
        printf("%d\n", MAXINT(int));
        printf("%ld\n", MAXINT(long));
        printf("%lld\n", MAXINT(off_t));
    }

On my I386 box the output from this test program is:

    127
    32767
    2147483647
    2147483647
    9223372036854775807

When changed to print hexadecimal output:

    #include <sys/types.h>
    #include <limits.h>
    #include <stdio.h>

    #define MAXINT(T) ((T) (((T)1 << ((sizeof(T) * CHAR_BIT) - 1) ^ ((T) -1))))

    main()
    {
        printf("0x%x\n", MAXINT(char));
        printf("0x%x\n", MAXINT(short));
        printf("0x%x\n", MAXINT(int));
        printf("0x%lx\n", MAXINT(long));
        printf("0x%llx\n", MAXINT(off_t));
    }

Output becomes:

    0x7f
    0x7fff
    0x7fffffff
    0x7fffffff
    0x7fffffffffffffff

It would be nice to hear how this works on 64-bit systems. I can
try this on SPARC/Solaris myself.

Up to this point I think I understand how and why the macro works.

However, if someone can explain to me why this produces 0xffffffff
for long long on I386, then I am all ears. Every day brings an
opportunity to learn something new about the C programming language.

        Wietse








Hosted Email Solutions

Invaluement Anti-Spam DNSBLs



Powered By FreeBSD   Powered By FreeBSD