_wstat on Windows (actually stat stuff in general)



In at least gstdio.c, possibly other places (I am still looking) there is a lot of code to use the "wide" versions of various functions like stat, because it is assumed that the input argument is UTF-8 and the CRT doesn't support UTF-8 directly but rather Microsoft's own multibyte character set stuff (MBCS). In almost all cases this is cool except for 1: stat. MSDN has this to say about _wstat:

"_wstat does not work with Windows Vista symbolic links. In these cases, _wstat will always report a file size of 0. _stat does work correctly with symbolic links."

So, for stat, we have to do a double conversion: first from the input UTF-8 to UTF-16, and then from UTF-16 to MBCS so that we can call stat instead of wstat so that users don't get any nasty surprises when using g_stat() on a symlink in Vista. *le sigh*

There is also a broader issue with stat. The size of struct stat can vary according to what macros are defined when you include <sys/stat.h>. If you have _FILE_OFFSET_BITS=64 defined your size fields are 64-bit, otherwise they *can* be 64-bit but are most often 32-bit. Thus, if glib was compiled without _FILE_OFFSET_BITS defined, and an application uses g_stat() but DOES have it defined, you're in for trouble (and the inverse is true - if glib was compiled with _FILE_OFFSET_BITS=64 and the app wasn't, the same hilarity ensues).

On almost all UNIX systems time_t is a signed 32-bit int thus capable of representing time from the epoch through some time in 2038. Windows has support for 64-bit time fields which is surprisingly forward thinking of them.

Since GLib is a "platform library" it would be extremely useful if gstsdio.h defined a GLib version of the stat structures instead of just doing "typedef struct stat GStatBuf". That structure can be consistently defined, with sufficiently large data types that it will work on all systems. Despire the coolness of Windows supporting time fields 64-bits wide for the least amount of pain it would probably be best if the time fields were left at 32-bits (although it would be really cool and forward thinking if we used 64-bits), but to use 64-bit fields for all size fields, and 32-bit fields for all others. That way gstdio.[ch] can be compiled in a very specific way to get the information needed and then smush it into that portable structure. Here's how I would define the GStatBuf data type:

typedef struct GStatBuf {
  guint32          st_dev;
  guint64          st_ino;
  guint16          st_mode;
  guint16          st_nlink;
  guint32          st_uid;
  guint32          st_gid;
  guint32          st_rdev;
  gint64           st_size;
  gint32           st_atime;
  gint32           st_mtime;
  gint32           st_ctime;
} GStatBuf;

We would of course add defines for things like G_S_IFDIR, G_S_IFMT etc that are also nice and portable (and the corresponding G_S_ISDIR type macros).

While in gstdio I'd also add the glaring-by-their-omission g_lseek, g_fseek, and g_ftell all of which could take a gint32 as their argument or return value.

A good case could be made for extending gtypes.h to include some primnitive types such a gtime_t, goffs_t etc and use those but that's just syntactic sugar really. Using the existing types would be just fine.

I'd really love to do this if no-one has any objections?

Kean


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