* configure.in, bcc32/Makefile.sub, win32/Makefile.sub, win32/dir.h,
  win32/win32.c, win32/win32.h: large file support for win32.


Index: configure.in
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/configure.in,v
retrieving revision 1.311
diff -U 2 -p -r1.311 configure.in
--- configure.in	7 Aug 2006 05:44:43 -0000	1.311
+++ configure.in	8 Aug 2006 13:52:47 -0000
@@ -219,4 +219,11 @@ dnl check for large file stuff
 AC_SYS_LARGEFILE
 
+case "$target_os" in
+mingw*)
+	ac_cv_type_off_t=yes
+	ac_cv_sizeof_off_t=8
+	;;
+esac
+
 AC_CHECK_TYPES([long long, off_t])
 
@@ -379,4 +386,7 @@ mingw*)		LIBS="-lshell32 -lws2_32 $LIBS"
 		ac_cv_func_finite=yes
 		ac_cv_func_link=yes
+		ac_cv_func_truncate=yes
+		ac_cv_func_fseeko=yes
+		ac_cv_func_ftello=yes
 		ac_cv_lib_crypt_crypt=no
 		ac_cv_func_getpgrp_void=no
Index: bcc32/Makefile.sub
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/bcc32/Makefile.sub,v
retrieving revision 1.87
diff -U 2 -p -r1.87 Makefile.sub
--- bcc32/Makefile.sub	25 May 2006 23:43:27 -0000	1.87
+++ bcc32/Makefile.sub	2 Aug 2006 05:25:07 -0000
@@ -215,4 +215,5 @@ $(CONFIG_H): $(MKFILES) $(srcdir)bcc32/M
 \#define HAVE_STRING_H 1
 \#define HAVE_MEMORY_H 1
+\#define HAVE_LONG_LONG 1
 \#define HAVE_OFF_T 1
 \#define SIZEOF_INT 4
@@ -221,5 +222,5 @@ $(CONFIG_H): $(MKFILES) $(srcdir)bcc32/M
 \#define SIZEOF_LONG_LONG 0
 \#define SIZEOF___INT64 8
-\#define SIZEOF_OFF_T 4
+\#define SIZEOF_OFF_T 8
 \#define SIZEOF_VOIDP 4
 \#define SIZEOF_FLOAT 4
@@ -265,5 +266,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)bcc32/M
 \#define HAVE_FSYNC 1
 \#define HAVE_GETCWD 1
-\#define HAVE_CHSIZE 1
+\#define HAVE_TRUNCATE 1
+\#define HAVE_FSEEKO 1
+\#define HAVE_FTELLO 1
 \#define HAVE_TIMES 1
 \#define HAVE_FCNTL 1
Index: win32/Makefile.sub
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/win32/Makefile.sub,v
retrieving revision 1.113
diff -U 2 -p -r1.113 Makefile.sub
--- win32/Makefile.sub	7 Jul 2006 05:08:05 -0000	1.113
+++ win32/Makefile.sub	2 Aug 2006 15:15:59 -0000
@@ -238,5 +238,6 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/
 !endif
 #define SIZEOF___INT64 8
-#define SIZEOF_OFF_T 4
+#define _INTEGRAL_MAX_BITS 64
+#define SIZEOF_OFF_T 8
 #define SIZEOF_VOIDP 4
 #define SIZEOF_FLOAT 4
@@ -298,5 +299,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/
 #define HAVE_FSYNC 1
 #define HAVE_GETCWD 1
-#define HAVE_CHSIZE 1
+#define HAVE_TRUNCATE 1
+#define HAVE_FSEEKO 1
+#define HAVE_FTELLO 1
 #define HAVE_TIMES 1
 #define HAVE_FCNTL 1
Index: win32/dir.h
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/win32/dir.h,v
retrieving revision 1.10
diff -U 2 -p -r1.10 dir.h
--- win32/dir.h	1 Jan 2006 05:49:01 -0000	1.10
+++ win32/dir.h	2 Aug 2006 05:25:07 -0000
@@ -30,6 +30,6 @@ typedef struct {
 DIR*           rb_w32_opendir(const char*);
 struct direct* rb_w32_readdir(DIR *);
-long           rb_w32_telldir(DIR *);
-void           rb_w32_seekdir(DIR *, long);
+off_t          rb_w32_telldir(DIR *);
+void           rb_w32_seekdir(DIR *, off_t);
 void           rb_w32_rewinddir(DIR *);
 void           rb_w32_closedir(DIR *);
Index: win32/win32.c
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/win32/win32.c,v
retrieving revision 1.194
diff -U 2 -p -r1.194 win32.c
--- win32/win32.c	31 Jul 2006 07:58:34 -0000	1.194
+++ win32/win32.c	11 Aug 2006 03:23:04 -0000
@@ -26,4 +26,5 @@
 #include <winbase.h>
 #include <wincon.h>
+#include <share.h>
 #include <shlobj.h>
 #ifdef __MINGW32__
@@ -1404,5 +1405,5 @@ rb_w32_opendir(const char *filename)
     char               scannamespc[PATHLEN];
     char	      *scanname = scannamespc;
-    struct stat	       sbuf;
+    struct stati64     sbuf;
     WIN32_FIND_DATA fd;
     HANDLE          fh;
@@ -1412,5 +1413,5 @@ rb_w32_opendir(const char *filename)
     //
 
-    if (rb_w32_stat(filename, &sbuf) < 0)
+    if (rb_w32_stati64(filename, &sbuf) < 0)
 	return NULL;
     if (!(sbuf.st_mode & S_IFDIR) &&
@@ -1571,5 +1572,5 @@ rb_w32_readdir(DIR *dirp)
 //
 
-long
+off_t
 rb_w32_telldir(DIR *dirp)
 {
@@ -1582,5 +1583,5 @@ rb_w32_telldir(DIR *dirp)
 
 void
-rb_w32_seekdir(DIR *dirp, long loc)
+rb_w32_seekdir(DIR *dirp, off_t loc)
 {
     rb_w32_rewinddir(dirp);
@@ -3224,4 +3225,18 @@ isUNCRoot(const char *path)
 }
 
+#define COPY_STAT(src, dest) do {		\
+	(dest).st_dev 	= (src).st_dev;		\
+	(dest).st_ino 	= (src).st_ino;		\
+	(dest).st_mode  = (src).st_mode;	\
+	(dest).st_nlink = (src).st_nlink;	\
+	(dest).st_uid   = (src).st_uid;		\
+	(dest).st_gid   = (src).st_gid;		\
+	(dest).st_rdev 	= (src).st_rdev;	\
+	(dest).st_size 	= (src).st_size;	\
+	(dest).st_atime = (src).st_atime;	\
+	(dest).st_mtime = (src).st_mtime;	\
+	(dest).st_ctime = (src).st_ctime;	\
+    } while (0)
+
 #ifdef __BORLANDC__
 #undef fstat
@@ -3240,4 +3255,23 @@ rb_w32_fstat(int fd, struct stat *st)
     return ret;
 }
+
+int
+rb_w32_fstati64(int fd, struct stati64 *st)
+{
+    BY_HANDLE_FILE_INFORMATION info;
+    struct stat tmp;
+    int ret = fstat(fd, &tmp);
+
+    if (ret) return ret;
+    tmp.st_mode &= ~(S_IWGRP | S_IWOTH);
+    COPY_STAT(tmp, *st);
+    if (GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &info)) {
+	if (!(info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
+	    st->st_mode |= S_IWUSR;
+	}
+	st->st_size = ((__int64)info.nFileSizeHigh << 32) | info.nFileSizeLow;
+    }
+    return ret;
+}
 #endif
 
@@ -3310,10 +3344,10 @@ fileattr_to_unixmode(DWORD attr, const c
 
 static int
-winnt_stat(const char *path, struct stat *st)
+winnt_stat(const char *path, struct stati64 *st)
 {
     HANDLE h;
     WIN32_FIND_DATA wfd;
 
-    memset(st, 0, sizeof(struct stat));
+    memset(st, 0, sizeof(*st));
     st->st_nlink = 1;
 
@@ -3329,5 +3363,5 @@ winnt_stat(const char *path, struct stat
 	st->st_mtime = filetime_to_unixtime(&wfd.ftLastWriteTime);
 	st->st_ctime = filetime_to_unixtime(&wfd.ftCreationTime);
-	st->st_size  = wfd.nFileSizeLow; /* TODO: 64bit support */
+	st->st_size = ((__int64)wfd.nFileSizeHigh << 32) | wfd.nFileSizeLow;
     }
     else {
@@ -3351,4 +3385,14 @@ int
 rb_w32_stat(const char *path, struct stat *st)
 {
+    struct stati64 tmp;
+
+    if (rb_w32_stati64(path, &tmp)) return -1;
+    COPY_STAT(tmp, *st);
+    return 0;
+}
+
+int
+rb_w32_stati64(const char *path, struct stati64 *st)
+{
     const char *p;
     char *buf1, *s, *end;
@@ -3380,8 +3424,9 @@ rb_w32_stat(const char *path, struct sta
 	else if (*end != '\\')
 	    strcat(buf1, "\\");
-    } else if (*end == '\\' || (buf1 + 1 == end && *end == ':'))
+    }
+    else if (*end == '\\' || (buf1 + 1 == end && *end == ':'))
 	strcat(buf1, ".");
 
-    ret = IsWinNT() ? winnt_stat(buf1, st) : stat(buf1, st);
+    ret = IsWinNT() ? winnt_stat(buf1, st) : stati64(buf1, st);
     if (ret == 0) {
 	st->st_mode &= ~(S_IWGRP | S_IWOTH);
@@ -3390,4 +3435,138 @@ rb_w32_stat(const char *path, struct sta
 }
 
+static int
+rb_chsize(HANDLE h, off_t size)
+{
+    long upos, lpos, usize, lsize, uend, lend;
+    off_t end;
+    int ret = -1;
+    DWORD e;
+
+    if (((lpos = SetFilePointer(h, 0, (upos = 0, &upos), SEEK_CUR)) == -1L &&
+	 (e = GetLastError())) ||
+	((lend = GetFileSize(h, (DWORD *)&uend)) == -1L && (e = GetLastError()))) {
+	errno = map_errno(e);
+	return -1;
+    }
+    end = ((off_t)uend << 32) | (unsigned long)lend;
+    usize = (long)(size >> 32);
+    lsize = (long)size;
+    if (SetFilePointer(h, lsize, &usize, SEEK_SET) == -1L &&
+	(e = GetLastError())) {
+	errno = map_errno(e);
+    }
+    else if (!SetEndOfFile(h)) {
+	errno = map_errno(GetLastError());
+    }
+    else {
+	ret = 0;
+    }
+    SetFilePointer(h, lpos, &upos, SEEK_SET);
+    return ret;
+}
+
+int
+truncate(const char *path, off_t length)
+{
+    HANDLE h;
+    int ret;
+    if (IsWin95()) {
+	int fd = open(path, O_WRONLY), e;
+	if (fd == -1) return -1;
+	ret = chsize(fd, (unsigned long)length);
+	if (ret == -1) e = errno;
+	close(fd);
+	if (ret == -1) errno = e;
+	return ret;
+    }
+    h = CreateFile(path, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
+    if (h == INVALID_HANDLE_VALUE) {
+	errno = map_errno(GetLastError());
+	return -1;
+    }
+    ret = rb_chsize(h, length);
+    CloseHandle(h);
+    return ret;
+}
+
+int
+ftruncate(int fd, off_t length)
+{
+    long h;
+
+    if (IsWin95()) {
+	return chsize(fd, (unsigned long)length);
+    }
+    h = _get_osfhandle(fd);
+    if (h == -1) return -1;
+    return rb_chsize((HANDLE)h, length);
+}
+
+#ifdef __BORLANDC__
+off_t
+_filelengthi64(int fd)
+{
+    DWORD u, l;
+    int e;
+
+    l = GetFileSize((HANDLE)_get_osfhandle(fd), &u);
+    if (l == (DWORD)-1L && (e = GetLastError())) {
+	errno = map_errno(e);
+	return (off_t)-1;
+    }
+    return ((off_t)u << 32) | l;
+}
+
+off_t
+_lseeki64(int fd, off_t offset, int whence)
+{
+    long u, l;
+    int e;
+    HANDLE h = (HANDLE)_get_osfhandle(fd);
+
+    if (!h) {
+	errno = EBADF;
+	return -1;
+    }
+    u = (long)(offset >> 32);
+    if ((l = SetFilePointer(h, (long)offset, &u, whence)) == -1L &&
+	(e = GetLastError())) {
+	errno = map_errno(e);
+	return -1;
+    }
+    return ((off_t)u << 32) | l;
+}
+#endif
+
+int
+fseeko(FILE *stream, off_t offset, int whence)
+{
+    off_t pos;
+    switch (whence) {
+      case SEEK_CUR:
+	if (fgetpos(stream, (fpos_t *)&pos))
+	    return -1;
+	pos += offset;
+	break;
+      case SEEK_END:
+	if ((pos = _filelengthi64(fileno(stream))) == (off_t)-1)
+	    return -1;
+	pos += offset;
+	break;
+      default:
+	pos = offset;
+	break;
+    }
+    return fsetpos(stream, (fpos_t *)&pos);
+}
+
+off_t
+ftello(FILE *stream)
+{
+    off_t pos;
+    if (fgetpos(stream, (fpos_t *)&pos)) return (off_t)-1;
+    return pos;
+}
+
 static long
 filetime_to_clock(FILETIME *ft)
@@ -3932,8 +4111,8 @@ rb_w32_utime(const char *path, const str
     FILETIME atime, mtime;
     struct tm *tm;
-    struct stat stat;
+    struct stati64 stat;
     int ret = 0;
 
-    if (rb_w32_stat(path, &stat)) {
+    if (rb_w32_stati64(path, &stat)) {
 	return -1;
     }
Index: win32/win32.h
===================================================================
RCS file: /pub/cvs/ruby/src/ruby/win32/win32.h,v
retrieving revision 1.79
diff -U 2 -p -r1.79 win32.h
--- win32/win32.h	27 Jun 2006 07:20:52 -0000	1.79
+++ win32/win32.h	11 Aug 2006 03:53:03 -0000
@@ -95,4 +95,6 @@ extern DWORD rb_w32_osid(void);
 #undef fputchar
 #undef utime
+#undef lseek
+#undef fstat
 #define getc(_stream)		rb_w32_getc(_stream)
 #define getchar()		rb_w32_getc(stdin)
@@ -105,4 +107,5 @@ extern DWORD rb_w32_osid(void);
 #define fputchar(_c)		putchar(_c)
 #define utime(_p, _t)		rb_w32_utime(_p, _t)
+#define lseek(_f, _o, _w)	_lseeki64(_f, _o, _w)
 
 #define pipe(p)			_pipe(p, 2048L, O_BINARY)
@@ -114,4 +117,5 @@ extern DWORD rb_w32_osid(void);
 #define sleep(x)		rb_w32_Sleep((x)*1000)
 #define Sleep(msec)		(void)rb_w32_Sleep(msec)
+#define fstat(fd,st)		_fstati64(fd,st)
 #ifdef __BORLANDC__
 #define creat(p, m)		_creat(p, m)
@@ -122,6 +126,5 @@ extern DWORD rb_w32_osid(void);
 #define _open			_sopen
 #define sopen			_sopen
-#undef fstat
-#define fstat(fd,st)		rb_w32_fstat(fd,st)
+#define _fstati64(fd,st)	rb_w32_fstati64(fd,st)
 #undef fopen
 #define fopen(p, m)		rb_w32_fopen(p, m)
@@ -132,6 +135,4 @@ extern DWORD rb_w32_osid(void);
 #endif
 
-#undef stat
-#define stat(path,st)		rb_w32_stat(path,st)
 #undef execv
 #define execv(path,argv)	rb_w32_aspawn(P_OVERLAY,path,argv)
@@ -149,4 +150,23 @@ extern DWORD rb_w32_osid(void);
 #endif
 
+#if SIZEOF_OFF_T == 8
+#define off_t __int64
+#define stat stati64
+#if defined(__BORLANDC__)
+#define stati64(path, st) rb_w32_stati64(path, st)
+#elif !defined(_MSC_VER) || _MSC_VER < 1400
+#define stati64 _stati64
+#define _stati64(path, st) rb_w32_stati64(path, st)
+#else
+#define stati64 _stat64
+#define _stat64(path, st) rb_w32_stati64(path, st)
+#endif
+#else
+#define stat(path,st)		rb_w32_stat(path,st)
+#define fstat(fd,st)		rb_w32_fstat(fd,st)
+extern int rb_w32_stat(const char *, struct stat *);
+extern int rb_w32_fstat(int, struct stat *);
+#endif
+
 #define strcasecmp(s1, s2)	stricmp(s1, s2)
 #define strncasecmp(s1, s2, n)	strnicmp(s1, s2, n)
@@ -221,8 +241,9 @@ extern int rb_w32_mkdir(const char *, in
 extern int rb_w32_rmdir(const char *);
 extern int rb_w32_unlink(const char *);
-extern int rb_w32_stat(const char *, struct stat *);
+extern int rb_w32_stati64(const char *, struct stati64 *);
 
 #ifdef __BORLANDC__
-extern int rb_w32_fstat(int, struct stat *);
+extern int rb_w32_fstati64(int, struct stati64 *);
+extern off_t _lseeki64(int, off_t, int);
 extern FILE *rb_w32_fopen(const char *, const char *);
 extern FILE *rb_w32_fdopen(int, const char *);
@@ -298,4 +319,8 @@ extern FILE *rb_w32_fsopen(const char *,
 
 #define SUFFIX
+extern int       truncate(const char *path, off_t length);
+extern int       ftruncate(int fd, off_t length);
+extern int       fseeko(FILE *stream, off_t offset, int whence);
+extern off_t     ftello(FILE *stream);
 
 //
