Skip to Content.
Sympa Menu

freetds - Re: [freetds] win64

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: "Frediano Ziglio" <freddy77 AT gmail.com>
  • To: "FreeTDS Development Group" <freetds AT lists.ibiblio.org>
  • Subject: Re: [freetds] win64
  • Date: Mon, 19 Jan 2009 10:18:05 +0100

2009/1/17 James K. Lowden <jklowden AT freetds.org>:
> Sometimes work guides The Work. I built FreeTDS for 64-bit Windows this
> week with VS 2005. I modified libtds to emit fewer warnings -- I left
> some that are pretty egregious -- and added a .sln and .vcproj files to
> the src directories.
>

good.. I would have put in win32 directory but it's ok.

> As far as I know, I'm the first one to do this. There was barely any
> support for it. For example, the winsock stuff was defined only for
> WIN32. It's a big patch.
>

???
are you sure ?? Do you know WIN32 is defined even for win64 ??

> What follows are some notes on what I did in case it helps anyone else.
>
> Win64 is an LLP64 architecture, whereas Linux uses LP64. The major
> difference is that a Win64 long integer is still 32 bits while a Linux
> long is 64 bits (cf.
> http://www.ibm.com/developerworks/library/l-port64.html and
> http://www.unix.org/version2/whatsnew/lp64_wp.html). size_t can hold the
> maximum difference between two pointers. In Linux, size_t is the same as
> an unsigned long. In Win64 there's no standard type equivalent to size_t.
>

intptr_t perhaps or something like that. There is also TDS_INTPTR !

>
> There's an inherent tension in the C standard library between integers and
> sizes. For example, strlen(3) returns size_t and sprintf(3) returns int.
> To be meaninful, the values being compared have to fit within both
> datatype's domains (which typically they do, but the compiler can't know
> that and the handling of the atypical case will likely hurt). .
>
> To squelch the warnings, we add a cast. To be safe, that cast really
> should be inside a conversion function that uses assert(3) to verify the
> size_t values fits in 31 bits. I didn't do that, but it would be IMO a
> worthwhile exercise.
>
> Simlilarly, libtds plays fast and loose with int and unsigned int. Most
> of the time it's really OK: how often will a column name length need more
> than 2^31 bits? I find myself wondering if we shouldn't have a function
> strleni() that returns an int after checking the size. .
>
> Another way to handle this would be to make widespread use of a union,
>
> typedef union tds_length {
> unsigned long ulong;
> size_t size;
> int len;
> } TDS_LENGTH;
>
> and use checking functions (or macros)
>
> size_t
> as_size( TDS_LENGTH L )
> {
> assert(L.len > 0);
> return L.size;
> }
>
> int
> as_int( TDS_LENGTH L )
> {
> assert(L.size <= INT_MAX);
> return L.len;
> }
>
> unsigned long
> as_ulong( TDS_LENGTH L )
> {
> assert(L.len > 0);
> return L.ulong;
> }
>
> to write such code as
>
> TDS_LENGTH a;
> a.len = sprintf(...);
> if( as_size(a) != strlen(...) )
> return FAIL;
>

it can't work !!! Think about endianess !!!

> That would constrain TDS_LENGTH to use values <= 2^31 is most cases. The
> functions *assume* you're using the structure for type-punning. Short of
> C++'s operator overloading, there's no easy way to check.
>
> There are many places in libtds particularly where int is used where
> size_t would have been more in keeping with the standard library. (I'm as
> guilty as anyone else; old habits are hard to break.) Often, the type is
> chosen to match a corresponding part of the TDS data strea, e.g.
> TDSRESULTINFO::row_size is TDS_INT because that's how column widths are
> defined in the TDS_ROWFMT2 packet. (But it's not used that way in
> practice. tds_alloc_row() defines its local row_size as TDS_UINT,
> accumulates the sizes of the columns, and assigns the sum to
> TDSRESULTINFO::row_size. It would have been better to use size_t after
> all.)
>

Ok, size_t is correct, however see how packet is readed from network
and how row is allocated. Column number is a 16 bit so there can be at
maximun 2^16 = 65536 columns so each column can contains up to 2^31 /
2^16 = 2^15. Considering that BLOBs occupy just few bytes and variable
columns occupy at maximun 8000 bytes... there is no limit... 31 bits
are sufficient for every rowset.

> I think it would be better to use standard C types within the library and
> as much as possible reserve casts to deal with TDS packets or API calls.
> I wonder what others have done. It's not an easy question to research.
>

Personally I think this patch it too big and contains a lot of changes
grouped in a single one:
- new defines for sybdb.h just to make some windows programs happy...
nothing related to win64
- use of newer _fseeki64 which break compatibility with old VS and even mingw
- changed inclusion styles. Are you sure that client programs works as
expected ??
- a lot of warning removed just adding casts
- added a log and a strange string copy in tds_put_login_string (with
a possible buffer overflow... I'll check it)
- winsocket initialization (why in mem.c and not in net.c ??)
- other minor styles changes

freddy77




Archive powered by MHonArc 2.6.24.

Top of Page