Hi,

2016/1/31 Sun 0:16:56 UTC+9 Ken Takata wrote:
> Hi,
> 
> 2016/1/31 Sun 0:02:07 UTC+9 Ken Takata wrote:
> > Hi,
> > 
> > 2016/1/30 Sat 12:51:11 UTC+9 Ken Takata wrote:
> > > Hi,
> > > 
> > > 2016/1/21 Thu 7:11:51 UTC+9 Bram Moolenaar wrote:
> > > > Ken Takata wrote:
> > > > 
> > > > > 2016/1/20 Wed 7:47:18 UTC+9 Ken Takata wrote:
> > > > > > Hi Bram,
> > > > > > 
> > > > > > 2016/1/20 Wed 3:33:18 UTC+9 Bram Moolenaar wrote:
> > > > > > > Ken Takata wrote:
> > > > > > > 
> > > > > > > > (The original thread was in vim_use:
> > > > > > > > https://groups.google.com/d/topic/vim_use/RLM8Vqa_aME/discussion
> > > > > > > >  )
> > > > > > > > 
> > > > > > > > I have updated the patches for supporting large files on 
> > > > > > > > Windows.
> > > > > > > > I also converted the test to the new style.  And I also added a 
> > > > > > > > new test for
> > > > > > > > large files: test_largefile.vim.  This creates a 4GB file, 
> > > > > > > > moving around it,
> > > > > > > > and write it to disk.  This uses over 8GB disk spaces, and 
> > > > > > > > consumes CPU
> > > > > > > > powers.  So I don't add this test to src/testdir/Make_all.mak.  
> > > > > > > > I confirmed
> > > > > > > > that when running the test without my fix, gvim.exe (32-bit) 
> > > > > > > > stopped with
> > > > > > > > "E342: Out of memory!" (takes about 10min), but it succeeded 
> > > > > > > > with my fix
> > > > > > > > (takes about 5min).
> > > > > > > > Please check the attached patches.
> > > > > > > > 
> > > > > > > > Note: Please apply the following patch before them to avoid 
> > > > > > > > conflicts.
> > > > > > > > https://groups.google.com/d/topic/vim_dev/JHbE4twU4dk/discussion
> > > > > > > 
> > > > > > > Thanks.  In what order do the patches need to be applied?
> > > > > > > Looks like the stat_T patch comes after the others?
> > > > > > 
> > > > > > Yes.
> > > > > > use-stat_T.patch must be applied after 
> > > > > > support-largefiles-on-windows.patch.
> > > > > > Other two are independent.
> > > > > > 
> > > > > > 
> > > > > > > For the test, we can add a "torture" target.
> > > > > > > 
> > > > > > > I have this old note in the todo file:
> > > > > > > 
> > > > > > > Win32: patch to use 64 bit stat() if possible. (Ken Takata, 2014 
> > > > > > > May 12)
> > > > > > > More tests May 14. Update May 29.  Update Aug 10.
> > > > > > > 
> > > > > > > I assume that is related to this?
> > > > > > 
> > > > > > Yes, the stat_T patch is a patch for this.
> > > > > > Without this patch, getfsize() returns a broken value (e.g. 
> > > > > > -294967296), if
> > > > > > the size of a file is larger than 2 GiB and smaller than 4 GiB. And 
> > > > > > if the
> > > > > > size is larger than 4 GiB, getfsize() and other stat functions 
> > > > > > return -1.
> > > > > > MSVC's 32-bit stat() always returns error if the filesize is larger 
> > > > > > than 4 GiB.
> > > > > 
> > > > > I wrote an additional patch to fix display of off_T value.
> > > > > add-stat-test.patch is updated to fix conflicts with 7.4.1142.
> > > > > Please apply in the following order:
> > > > > 
> > > > > 1. support-largefiles-on-windows.patch (previous mail)
> > > > > 2. fix-off_T-display.patch  (this mail)
> > > > > 3. use-stat_T.patch     (previous mail)
> > > > > 4. add-stat-test.patch  (this mail)
> > > > > 5. test_largefile.patch (previous mail)
> > > > 
> > > > Thanks!
> > > 
> > > Here are the updated large files patch for 7.4.1202.
> > 
> > And... this is for 7.4.1205.
> 
> Oops, I sent my update too early.
> I have to wait all the style changes have completed.

I think that all the style changes have completed.
Here are the updated large file patches for 7.4.1229.

Regards,
Ken Takata

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
# HG changeset patch
# Parent 77eb2adaee0cedf71cd7949557fc841b8e177b4a
# Parent  e53c47128ccfe447e4ef64f0334457cf94e7eb13

diff --git a/src/eval.c b/src/eval.c
--- a/src/eval.c
+++ b/src/eval.c
@@ -11968,7 +11968,7 @@ f_getfsize(typval_T *argvars, typval_T *
 	    rettv->vval.v_number = (varnumber_T)st.st_size;
 
 	    /* non-perfect check for overflow */
-	    if ((off_t)rettv->vval.v_number != (off_t)st.st_size)
+	    if ((off_T)rettv->vval.v_number != (off_T)st.st_size)
 		rettv->vval.v_number = -2;
 	}
     }
diff --git a/src/fileio.c b/src/fileio.c
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -41,7 +41,7 @@ static char_u *readfile_charconvert(char
 static void check_marks_read(void);
 #endif
 #ifdef FEAT_CRYPT
-static char_u *check_for_cryptkey(char_u *cryptkey, char_u *ptr, long *sizep, off_t *filesizep, int newfile, char_u *fname, int *did_ask);
+static char_u *check_for_cryptkey(char_u *cryptkey, char_u *ptr, long *sizep, off_T *filesizep, int newfile, char_u *fname, int *did_ask);
 #endif
 #ifdef UNIX
 static void set_file_time(char_u *fname, time_t atime, time_t mtime);
@@ -233,7 +233,7 @@ readfile(
     colnr_T	len;
     long	size = 0;
     char_u	*p;
-    off_t	filesize = 0;
+    off_T	filesize = 0;
     int		skip_read = FALSE;
 #ifdef FEAT_CRYPT
     char_u	*cryptkey = NULL;
@@ -869,7 +869,7 @@ readfile(
 		/* Read the first line (and a bit more).  Immediately rewind to
 		 * the start of the file.  If the read() fails "len" is -1. */
 		len = read_eintr(fd, firstline, 80);
-		lseek(fd, (off_t)0L, SEEK_SET);
+		vim_lseek(fd, (off_T)0L, SEEK_SET);
 		for (p = firstline; p < firstline + len; ++p)
 		    if (*p >= 0x80)
 		    {
@@ -933,7 +933,7 @@ retry:
 	    read_buf_lnum = 1;
 	    read_buf_col = 0;
 	}
-	else if (read_stdin || lseek(fd, (off_t)0L, SEEK_SET) != 0)
+	else if (read_stdin || vim_lseek(fd, (off_T)0L, SEEK_SET) != 0)
 	{
 	    /* Can't rewind the file, give up. */
 	    error = TRUE;
@@ -2237,7 +2237,8 @@ rewind_retry:
 				if (   try_unix
 				    && !read_stdin
 				    && (read_buffer
-					|| lseek(fd, (off_t)0L, SEEK_SET) == 0))
+					|| vim_lseek(fd, (off_T)0L, SEEK_SET)
+									  == 0))
 				{
 				    fileformat = EOL_UNIX;
 				    if (set_options)
@@ -2933,7 +2934,7 @@ check_for_cryptkey(
     char_u	*cryptkey,	/* previous encryption key or NULL */
     char_u	*ptr,		/* pointer to read bytes */
     long	*sizep,		/* length of read bytes */
-    off_t	*filesizep,	/* nr of bytes used from file */
+    off_T	*filesizep,	/* nr of bytes used from file */
     int		newfile,	/* editing a new buffer */
     char_u	*fname,		/* file name to display */
     int		*did_ask)	/* flag: whether already asked for key */
@@ -5213,7 +5214,7 @@ msg_add_fileformat(int eol_type)
 msg_add_lines(
     int	    insert_space,
     long    lnum,
-    off_t   nchars)
+    off_T   nchars)
 {
     char_u  *p;
 
@@ -6787,7 +6788,7 @@ buf_check_timestamp(
 #if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
     int		can_reload = FALSE;
 #endif
-    off_t	orig_size = buf->b_orig_size;
+    off_T	orig_size = buf->b_orig_size;
     int		orig_mode = buf->b_orig_mode;
 #ifdef FEAT_GUI
     int		save_mouse_correct = need_mouse_correct;
diff --git a/src/memfile.c b/src/memfile.c
--- a/src/memfile.c
+++ b/src/memfile.c
@@ -81,7 +81,7 @@ static void mf_ins_free(memfile_T *, bhd
 static bhdr_T *mf_rem_free(memfile_T *);
 static int  mf_read(memfile_T *, bhdr_T *);
 static int  mf_write(memfile_T *, bhdr_T *);
-static int  mf_write_block(memfile_T *mfp, bhdr_T *hp, off_t offset, unsigned size);
+static int  mf_write_block(memfile_T *mfp, bhdr_T *hp, off_T offset, unsigned size);
 static int  mf_trans_add(memfile_T *, bhdr_T *);
 static void mf_do_open(memfile_T *, char_u *, int);
 static void mf_hash_init(mf_hashtab_T *);
@@ -124,7 +124,7 @@ static int mf_hash_grow(mf_hashtab_T *);
 mf_open(char_u *fname, int flags)
 {
     memfile_T		*mfp;
-    off_t		size;
+    off_T		size;
 #if defined(STATFS) && defined(UNIX) && !defined(__QNX__) && !defined(__minix)
 # define USE_FSTATFS
     struct STATFS	stf;
@@ -179,7 +179,7 @@ mf_open(char_u *fname, int flags)
 #endif
 
     if (mfp->mf_fd < 0 || (flags & (O_TRUNC|O_EXCL))
-		      || (size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0)
+		  || (size = vim_lseek(mfp->mf_fd, (off_T)0L, SEEK_END)) <= 0)
 	mfp->mf_blocknr_max = 0;	/* no file or empty file */
     else
 	mfp->mf_blocknr_max = (blocknr_T)((size + mfp->mf_page_size - 1)
@@ -971,7 +971,7 @@ mf_rem_free(memfile_T *mfp)
     static int
 mf_read(memfile_T *mfp, bhdr_T *hp)
 {
-    off_t	offset;
+    off_T	offset;
     unsigned	page_size;
     unsigned	size;
 
@@ -979,9 +979,9 @@ mf_read(memfile_T *mfp, bhdr_T *hp)
 	return FAIL;
 
     page_size = mfp->mf_page_size;
-    offset = (off_t)page_size * hp->bh_bnum;
+    offset = (off_T)page_size * hp->bh_bnum;
     size = page_size * hp->bh_page_count;
-    if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset)
+    if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset)
     {
 	PERROR(_("E294: Seek error in swap file read"));
 	return FAIL;
@@ -1010,7 +1010,7 @@ mf_read(memfile_T *mfp, bhdr_T *hp)
     static int
 mf_write(memfile_T *mfp, bhdr_T *hp)
 {
-    off_t	offset;	    /* offset in the file */
+    off_T	offset;	    /* offset in the file */
     blocknr_T	nr;	    /* block nr which is being written */
     bhdr_T	*hp2;
     unsigned	page_size;  /* number of bytes in a page */
@@ -1043,8 +1043,8 @@ mf_write(memfile_T *mfp, bhdr_T *hp)
 	else
 	    hp2 = hp;
 
-	offset = (off_t)page_size * nr;
-	if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset)
+	offset = (off_T)page_size * nr;
+	if (vim_lseek(mfp->mf_fd, offset, SEEK_SET) != offset)
 	{
 	    PERROR(_("E296: Seek error in swap file write"));
 	    return FAIL;
@@ -1088,7 +1088,7 @@ mf_write(memfile_T *mfp, bhdr_T *hp)
 mf_write_block(
     memfile_T	*mfp,
     bhdr_T	*hp,
-    off_t	offset UNUSED,
+    off_T	offset UNUSED,
     unsigned	size)
 {
     char_u	*data = hp->bh_data;
diff --git a/src/memline.c b/src/memline.c
--- a/src/memline.c
+++ b/src/memline.c
@@ -266,7 +266,7 @@ static long char_to_long(char_u *);
 static char_u *make_percent_swname(char_u *dir, char_u *name);
 #endif
 #ifdef FEAT_CRYPT
-static cryptstate_T *ml_crypt_prepare(memfile_T *mfp, off_t offset, int reading);
+static cryptstate_T *ml_crypt_prepare(memfile_T *mfp, off_T offset, int reading);
 #endif
 #ifdef FEAT_BYTEOFF
 static void ml_updatechunk(buf_T *buf, long line, long len, int updtype);
@@ -1134,7 +1134,7 @@ ml_recover(void)
     int		idx;
     int		top;
     int		txt_start;
-    off_t	size;
+    off_T	size;
     int		called_from_main;
     int		serious_error = TRUE;
     long	mtime;
@@ -1330,7 +1330,7 @@ ml_recover(void)
 	    msg_end();
 	    goto theend;
 	}
-	if ((size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0)
+	if ((size = vim_lseek(mfp->mf_fd, (off_T)0L, SEEK_END)) <= 0)
 	    mfp->mf_blocknr_max = 0;	    /* no file or empty file */
 	else
 	    mfp->mf_blocknr_max = (blocknr_T)(size / mfp->mf_page_size);
@@ -4804,7 +4804,7 @@ ml_setflags(buf_T *buf)
 ml_encrypt_data(
     memfile_T	*mfp,
     char_u	*data,
-    off_t	offset,
+    off_T	offset,
     unsigned	size)
 {
     DATA_BL	*dp = (DATA_BL *)data;
@@ -4849,7 +4849,7 @@ ml_encrypt_data(
 ml_decrypt_data(
     memfile_T	*mfp,
     char_u	*data,
-    off_t	offset,
+    off_T	offset,
     unsigned	size)
 {
     DATA_BL	*dp = (DATA_BL *)data;
@@ -4883,7 +4883,7 @@ ml_decrypt_data(
  * Return an allocated cryptstate_T *.
  */
     static cryptstate_T *
-ml_crypt_prepare(memfile_T *mfp, off_t offset, int reading)
+ml_crypt_prepare(memfile_T *mfp, off_T offset, int reading)
 {
     buf_T	*buf = mfp->mf_buffer;
     char_u	salt[50];
diff --git a/src/netbeans.c b/src/netbeans.c
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -553,7 +553,7 @@ static void addsigntype(nbbuf_T *, int l
 			char_u *tooltip, char_u *glyphfile,
 			char_u *fg, char_u *bg);
 static void print_read_msg(nbbuf_T *buf);
-static void print_save_msg(nbbuf_T *buf, off_t nchars);
+static void print_save_msg(nbbuf_T *buf, off_T nchars);
 
 static int curPCtype = -1;
 
@@ -3401,7 +3401,7 @@ pos2off(buf_T *buf, pos_T *pos)
 print_read_msg(nbbuf_T *buf)
 {
     int	    lnum = buf->bufp->b_ml.ml_line_count;
-    off_t   nchars = buf->bufp->b_orig_size;
+    off_T   nchars = buf->bufp->b_orig_size;
     char_u  c;
 
     msg_add_fname(buf->bufp, buf->bufp->b_ffname);
@@ -3435,7 +3435,7 @@ print_read_msg(nbbuf_T *buf)
  * writing a file.
  */
     static void
-print_save_msg(nbbuf_T *buf, off_t nchars)
+print_save_msg(nbbuf_T *buf, off_T nchars)
 {
     char_u	c;
     char_u	*p;
diff --git a/src/proto/fileio.pro b/src/proto/fileio.pro
--- a/src/proto/fileio.pro
+++ b/src/proto/fileio.pro
@@ -7,7 +7,7 @@ void set_forced_fenc(exarg_T *eap);
 int check_file_readonly(char_u *fname, int perm);
 int buf_write(buf_T *buf, char_u *fname, char_u *sfname, linenr_T start, linenr_T end, exarg_T *eap, int append, int forceit, int reset_changed, int filtering);
 void msg_add_fname(buf_T *buf, char_u *fname);
-void msg_add_lines(int insert_space, long lnum, off_t nchars);
+void msg_add_lines(int insert_space, long lnum, off_T nchars);
 char_u *shorten_fname1(char_u *full_path);
 char_u *shorten_fname(char_u *full_path, char_u *dir_name);
 void shorten_fnames(int force);
diff --git a/src/proto/memline.pro b/src/proto/memline.pro
--- a/src/proto/memline.pro
+++ b/src/proto/memline.pro
@@ -30,8 +30,8 @@ int resolve_symlink(char_u *fname, char_
 char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name);
 char_u *get_file_in_dir(char_u *fname, char_u *dname);
 void ml_setflags(buf_T *buf);
-char_u *ml_encrypt_data(memfile_T *mfp, char_u *data, off_t offset, unsigned size);
-void ml_decrypt_data(memfile_T *mfp, char_u *data, off_t offset, unsigned size);
+char_u *ml_encrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned size);
+void ml_decrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned size);
 long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp);
 void goto_byte(long cnt);
 /* vim: set ft=c : */
diff --git a/src/structs.h b/src/structs.h
--- a/src/structs.h
+++ b/src/structs.h
@@ -1444,7 +1444,7 @@ struct file_buffer
 
     long	b_mtime;	/* last change time of original file */
     long	b_mtime_read;	/* last change time when reading */
-    off_t	b_orig_size;	/* size of original file in bytes */
+    off_T	b_orig_size;	/* size of original file in bytes */
     int		b_orig_mode;	/* mode of original file */
 
     pos_T	b_namedm[NMARKS]; /* current named marks (mark.c) */
diff --git a/src/tag.c b/src/tag.c
--- a/src/tag.c
+++ b/src/tag.c
@@ -83,15 +83,6 @@ static char_u *topmsg = (char_u *)N_("E5
 
 static char_u	*tagmatchname = NULL;	/* name of last used tag */
 
-/*
- * We use ftello() here, if available.  It returns off_t instead of long,
- * which helps if long is 32 bit and off_t is 64 bit.
- * We assume that when fseeko() is available then ftello() is too.
- */
-#ifdef HAVE_FSEEKO
-# define ftell ftello
-#endif
-
 #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
 /*
  * Tag for preview window is remembered separately, to avoid messing up the
@@ -1289,19 +1280,19 @@ find_tags(
     int		tag_file_sorted = NUL;	/* !_TAG_FILE_SORTED value */
     struct tag_search_info	/* Binary search file offsets */
     {
-	off_t	low_offset;	/* offset for first char of first line that
+	off_T	low_offset;	/* offset for first char of first line that
 				   could match */
-	off_t	high_offset;	/* offset of char after last line that could
+	off_T	high_offset;	/* offset of char after last line that could
 				   match */
-	off_t	curr_offset;	/* Current file offset in search range */
-	off_t	curr_offset_used; /* curr_offset used when skipping back */
-	off_t	match_offset;	/* Where the binary search found a tag */
+	off_T	curr_offset;	/* Current file offset in search range */
+	off_T	curr_offset_used; /* curr_offset used when skipping back */
+	off_T	match_offset;	/* Where the binary search found a tag */
 	int	low_char;	/* first char at low_offset */
 	int	high_char;	/* first char at high_offset */
     } search_info;
-    off_t	filesize;
+    off_T	filesize;
     int		tagcmp;
-    off_t	offset;
+    off_T	offset;
     int		round;
 #endif
     enum
@@ -1632,25 +1623,17 @@ find_tags(
 	    {
 		/* Adjust the search file offset to the correct position */
 		search_info.curr_offset_used = search_info.curr_offset;
-#ifdef HAVE_FSEEKO
-		fseeko(fp, search_info.curr_offset, SEEK_SET);
-#else
-		fseek(fp, (long)search_info.curr_offset, SEEK_SET);
-#endif
+		vim_fseek(fp, search_info.curr_offset, SEEK_SET);
 		eof = tag_fgets(lbuf, LSIZE, fp);
 		if (!eof && search_info.curr_offset != 0)
 		{
 		    /* The explicit cast is to work around a bug in gcc 3.4.2
 		     * (repeated below). */
-		    search_info.curr_offset = ftell(fp);
+		    search_info.curr_offset = vim_ftell(fp);
 		    if (search_info.curr_offset == search_info.high_offset)
 		    {
 			/* oops, gone a bit too far; try from low offset */
-#ifdef HAVE_FSEEKO
-			fseeko(fp, search_info.low_offset, SEEK_SET);
-#else
-			fseek(fp, (long)search_info.low_offset, SEEK_SET);
-#endif
+			vim_fseek(fp, search_info.low_offset, SEEK_SET);
 			search_info.curr_offset = search_info.low_offset;
 		    }
 		    eof = tag_fgets(lbuf, LSIZE, fp);
@@ -1658,14 +1641,14 @@ find_tags(
 		/* skip empty and blank lines */
 		while (!eof && vim_isblankline(lbuf))
 		{
-		    search_info.curr_offset = ftell(fp);
+		    search_info.curr_offset = vim_ftell(fp);
 		    eof = tag_fgets(lbuf, LSIZE, fp);
 		}
 		if (eof)
 		{
 		    /* Hit end of file.  Skip backwards. */
 		    state = TS_SKIP_BACK;
-		    search_info.match_offset = ftell(fp);
+		    search_info.match_offset = vim_ftell(fp);
 		    search_info.curr_offset = search_info.curr_offset_used;
 		    continue;
 		}
@@ -1891,12 +1874,12 @@ line_read_in:
 		{
 		    /* Get the tag file size (don't use mch_fstat(), it's not
 		     * portable). */
-		    if ((filesize = lseek(fileno(fp),
-						   (off_t)0L, SEEK_END)) <= 0)
+		    if ((filesize = vim_lseek(fileno(fp),
+						   (off_T)0L, SEEK_END)) <= 0)
 			state = TS_LINEAR;
 		    else
 		    {
-			lseek(fileno(fp), (off_t)0L, SEEK_SET);
+			vim_lseek(fileno(fp), (off_T)0L, SEEK_SET);
 
 			/* Calculate the first read offset in the file.  Start
 			 * the search in the middle of the file. */
@@ -1948,11 +1931,7 @@ parse_line:
 			    /* Avoid getting stuck. */
 			    linear = TRUE;
 			    state = TS_LINEAR;
-# ifdef HAVE_FSEEKO
-			    fseeko(fp, search_info.low_offset, SEEK_SET);
-# else
-			    fseek(fp, (long)search_info.low_offset, SEEK_SET);
-# endif
+			    vim_fseek(fp, search_info.low_offset, SEEK_SET);
 			}
 #endif
 			continue;
@@ -2050,7 +2029,7 @@ parse_line:
 		    }
 		    if (tagcmp < 0)
 		    {
-			search_info.curr_offset = ftell(fp);
+			search_info.curr_offset = vim_ftell(fp);
 			if (search_info.curr_offset < search_info.high_offset)
 			{
 			    search_info.low_offset = search_info.curr_offset;
@@ -2091,7 +2070,7 @@ parse_line:
 		{
 		    if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0)
 		    {
-			if ((off_t)ftell(fp) > search_info.match_offset)
+			if ((off_T)vim_ftell(fp) > search_info.match_offset)
 			    break;	/* past last match */
 			else
 			    continue;	/* before first match */
@@ -2434,7 +2413,7 @@ parse_line:
 #ifdef FEAT_CSCOPE
 	    if (!use_cscope)
 #endif
-		EMSGN(_("Before byte %ld"), (long)ftell(fp));
+		EMSGN(_("Before byte %ld"), (long)vim_ftell(fp));
 	    stop_searching = TRUE;
 	    line_error = FALSE;
 	}
diff --git a/src/vim.h b/src/vim.h
--- a/src/vim.h
+++ b/src/vim.h
@@ -421,6 +421,36 @@ typedef		 long __w64     long_i;
 #endif
 
 /*
+ * We use 64-bit file functions here, if available.  E.g. ftello() returns
+ * off_t instead of long, which helps if long is 32 bit and off_t is 64 bit.
+ * We assume that when fseeko() is available then ftello() is too.
+ * Note that Windows has different function names.
+ */
+#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__)
+typedef __int64 off_T;
+# ifdef __MINGW32__
+#  define vim_lseek lseek64
+#  define vim_fseek fseeko64
+#  define vim_ftell ftello64
+# else
+#  define vim_lseek _lseeki64
+#  define vim_fseek _fseeki64
+#  define vim_ftell _ftelli64
+# endif
+#else
+typedef off_t off_T;
+# ifdef HAVE_FSEEKO
+#  define vim_lseek lseek
+#  define vim_ftell ftello
+#  define vim_fseek fseeko
+# else
+#  define vim_lseek lseek
+#  define vim_ftell ftell
+#  define vim_fseek(a, b, c)	fseek(a, (long)b, c)
+# endif
+#endif
+
+/*
  * The characters and attributes cached for the screen.
  */
 typedef char_u schar_T;
@@ -1978,6 +2008,19 @@ typedef int sock_T;
 # endif
 #endif
 
+/* Use 64-bit stat functions if available. */
+#if ((defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__)) \
+					&& !defined(IN_PERL_FILE)
+# undef stat
+# undef _stat
+# undef _wstat
+# undef _fstat
+# define stat _stat64
+# define _stat _stat64
+# define _wstat _wstat64
+# define _fstat _fstat64
+#endif
+
 #include "ex_cmds.h"	    /* Ex command defines */
 #include "proto.h"	    /* function prototypes */
 
# HG changeset patch
# Parent  8e1a5942d28470b73afa3631e6b129f9b9f1b02a

diff --git a/src/fileio.c b/src/fileio.c
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5238,6 +5238,8 @@ msg_add_lines(insert_space, lnum, nchars
 	sprintf((char *)p,
 #ifdef LONG_LONG_OFF_T
 		"%ldL, %lldC", lnum, (long long)nchars
+#elif defined(WIN3264)
+		"%ldL, %I64dC", lnum, (__int64)nchars
 #else
 		/* Explicit typecast avoids warning on Mac OS X 10.6 */
 		"%ldL, %ldC", lnum, (long)nchars
@@ -5256,6 +5258,8 @@ msg_add_lines(insert_space, lnum, nchars
 	    sprintf((char *)p,
 #ifdef LONG_LONG_OFF_T
 		    _("%lld characters"), (long long)nchars
+#elif defined(WIN3264)
+		    _("%I64d characters"), (__int64)nchars
 #else
 		    /* Explicit typecast avoids warning on Mac OS X 10.6 */
 		    _("%ld characters"), (long)nchars
# HG changeset patch
# Parent a1d2cd2af94c52ff4d3e82f9241fdd5cbec88c6e
# Parent  79d8add73341f8703918c7c531ac0fe986588311

diff --git a/src/buffer.c b/src/buffer.c
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -35,9 +35,9 @@ static char_u	*fname_match(regmatch_T *r
 static void	buflist_setfpos(buf_T *buf, win_T *win, linenr_T lnum, colnr_T col, int copy_options);
 static wininfo_T *find_wininfo(buf_T *buf, int skip_diff_buffer);
 #ifdef UNIX
-static buf_T	*buflist_findname_stat(char_u *ffname, struct stat *st);
-static int	otherfile_buf(buf_T *buf, char_u *ffname, struct stat *stp);
-static int	buf_same_ino(buf_T *buf, struct stat *stp);
+static buf_T	*buflist_findname_stat(char_u *ffname, stat_T *st);
+static int	otherfile_buf(buf_T *buf, char_u *ffname, stat_T *stp);
+static int	buf_same_ino(buf_T *buf, stat_T *stp);
 #else
 static int	otherfile_buf(buf_T *buf, char_u *ffname);
 #endif
@@ -1650,7 +1650,7 @@ buflist_new(
 {
     buf_T	*buf;
 #ifdef UNIX
-    struct stat	st;
+    stat_T	st;
 #endif
 
     fname_expand(curbuf, &ffname, &sfname);	/* will allocate ffname */
@@ -2170,7 +2170,7 @@ buflist_findname_exp(char_u *fname)
 buflist_findname(char_u *ffname)
 {
 #ifdef UNIX
-    struct stat st;
+    stat_T	st;
 
     if (mch_stat((char *)ffname, &st) < 0)
 	st.st_dev = (dev_T)-1;
@@ -2185,7 +2185,7 @@ buflist_findname(char_u *ffname)
     static buf_T *
 buflist_findname_stat(
     char_u	*ffname,
-    struct stat	*stp)
+    stat_T	*stp)
 {
 #endif
     buf_T	*buf;
@@ -2834,7 +2834,7 @@ setfname(
 {
     buf_T	*obuf = NULL;
 #ifdef UNIX
-    struct stat st;
+    stat_T	st;
 #endif
 
     if (ffname == NULL || *ffname == NUL)
@@ -3073,7 +3073,7 @@ otherfile_buf(
     buf_T		*buf,
     char_u		*ffname
 #ifdef UNIX
-    , struct stat	*stp
+    , stat_T		*stp
 #endif
     )
 {
@@ -3084,9 +3084,9 @@ otherfile_buf(
 	return FALSE;
 #ifdef UNIX
     {
-	struct stat	st;
-
-	/* If no struct stat given, get it now */
+	stat_T	    st;
+
+	/* If no stat_T given, get it now */
 	if (stp == NULL)
 	{
 	    if (!buf->b_dev_valid || mch_stat((char *)ffname, &st) < 0)
@@ -3121,7 +3121,7 @@ otherfile_buf(
     void
 buf_setino(buf_T *buf)
 {
-    struct stat	st;
+    stat_T	st;
 
     if (buf->b_fname != NULL && mch_stat((char *)buf->b_fname, &st) >= 0)
     {
@@ -3139,7 +3139,7 @@ buf_setino(buf_T *buf)
     static int
 buf_same_ino(
     buf_T	*buf,
-    struct stat *stp)
+    stat_T	*stp)
 {
     return (buf->b_dev_valid
 	    && stp->st_dev == buf->b_dev
diff --git a/src/diff.c b/src/diff.c
--- a/src/diff.c
+++ b/src/diff.c
@@ -888,7 +888,7 @@ ex_diffpatch(exarg_T *eap)
     char_u	*browseFile = NULL;
     int		browse_flag = cmdmod.browse;
 #endif
-    struct stat st;
+    stat_T	st;
 
 #ifdef FEAT_BROWSE
     if (cmdmod.browse)
diff --git a/src/eval.c b/src/eval.c
--- a/src/eval.c
+++ b/src/eval.c
@@ -11923,7 +11923,7 @@ f_getfontname(typval_T *argvars UNUSED, 
 f_getfperm(typval_T *argvars, typval_T *rettv)
 {
     char_u	*fname;
-    struct stat st;
+    stat_T	st;
     char_u	*perm = NULL;
     char_u	flags[] = "rwx";
     int		i;
@@ -11953,7 +11953,7 @@ f_getfperm(typval_T *argvars, typval_T *
 f_getfsize(typval_T *argvars, typval_T *rettv)
 {
     char_u	*fname;
-    struct stat	st;
+    stat_T	st;
 
     fname = get_tv_string(&argvars[0]);
 
@@ -11983,7 +11983,7 @@ f_getfsize(typval_T *argvars, typval_T *
 f_getftime(typval_T *argvars, typval_T *rettv)
 {
     char_u	*fname;
-    struct stat	st;
+    stat_T	st;
 
     fname = get_tv_string(&argvars[0]);
 
@@ -12000,7 +12000,7 @@ f_getftime(typval_T *argvars, typval_T *
 f_getftype(typval_T *argvars, typval_T *rettv)
 {
     char_u	*fname;
-    struct stat st;
+    stat_T	st;
     char_u	*type = NULL;
     char	*t;
 
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -1838,14 +1838,14 @@ write_viminfo(char_u *file, int forceit)
     FILE	*fp_in = NULL;	/* input viminfo file, if any */
     FILE	*fp_out = NULL;	/* output viminfo file */
     char_u	*tempname = NULL;	/* name of temp viminfo file */
-    struct stat	st_new;		/* mch_stat() of potential new file */
+    stat_T	st_new;		/* mch_stat() of potential new file */
     char_u	*wp;
 #if defined(UNIX) || defined(VMS)
     mode_t	umask_save;
 #endif
 #ifdef UNIX
     int		shortname = FALSE;	/* use 8.3 file name */
-    struct stat	st_old;		/* mch_stat() of existing viminfo file */
+    stat_T	st_old;		/* mch_stat() of existing viminfo file */
 #endif
 #ifdef WIN3264
     int		hidden = FALSE;
@@ -3074,7 +3074,7 @@ not_writing(void)
     static int
 check_readonly(int *forceit, buf_T *buf)
 {
-    struct stat	st;
+    stat_T	st;
 
     /* Handle a file being readonly when the 'readonly' option is set or when
      * the file exists and permissions are read-only.
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -3203,7 +3203,7 @@ do_source(
     int			    save_debug_break_level = debug_break_level;
     scriptitem_T	    *si = NULL;
 # ifdef UNIX
-    struct stat		    st;
+    stat_T		    st;
     int			    stat_ok;
 # endif
 #endif
diff --git a/src/fileio.c b/src/fileio.c
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -49,7 +49,7 @@ static void set_file_time(char_u *fname,
 static int set_rw_fname(char_u *fname, char_u *sfname);
 static int msg_add_fileformat(int eol_type);
 static void msg_add_eol(void);
-static int check_mtime(buf_T *buf, struct stat *s);
+static int check_mtime(buf_T *buf, stat_T *s);
 static int time_differs(long t1, long t2);
 #ifdef FEAT_AUTOCMD
 static int apply_autocmds_exarg(event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap);
@@ -257,7 +257,7 @@ readfile(
 #endif
     int		fileformat = 0;		/* end-of-line format */
     int		keep_fileformat = FALSE;
-    struct stat	st;
+    stat_T	st;
     int		file_readonly;
     linenr_T	skip_count = 0;
     linenr_T	read_count = 0;
@@ -3121,7 +3121,7 @@ buf_write(
     int		    overwriting;	    /* TRUE if writing over original */
     int		    no_eol = FALSE;	    /* no end-of-line written */
     int		    device = FALSE;	    /* writing to a device */
-    struct stat	    st_old;
+    stat_T	    st_old;
     int		    prev_got_int = got_int;
     int		    file_readonly = FALSE;  /* overwritten file is read-only */
     static char	    *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
@@ -3650,7 +3650,7 @@ buf_write(
     if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup)
     {
 #if defined(UNIX) || defined(WIN32)
-	struct stat st;
+	stat_T	    st;
 #endif
 
 	if ((bkc & BKC_YES) || append)	/* "yes" */
@@ -3789,7 +3789,7 @@ buf_write(
 	    int		bfd;
 	    char_u	*copybuf, *wp;
 	    int		some_error = FALSE;
-	    struct stat	st_new;
+	    stat_T	st_new;
 	    char_u	*dirp;
 	    char_u	*rootname;
 #if defined(UNIX) && !defined(SHORT_FNAME)
@@ -4331,7 +4331,7 @@ buf_write(
 	if (errmsg == NULL)
 	{
 #ifdef UNIX
-	    struct stat	st;
+	    stat_T	st;
 
 	    /* Don't delete the file when it's a hard or symbolic link. */
 	    if ((!newfile && st_old.st_nlink > 1)
@@ -4364,7 +4364,7 @@ buf_write(
 
 restore_backup:
 	{
-	    struct stat st;
+	    stat_T	st;
 
 	    /*
 	     * If we failed to open the file, we don't need a backup. Throw it
@@ -4661,7 +4661,7 @@ restore_backup:
     if (backup != NULL && !backup_copy)
     {
 # ifdef HAVE_FCHOWN
-	struct stat	st;
+	stat_T	st;
 
 	/* don't change the owner when it's already OK, some systems remove
 	 * permission or ACL stuff */
@@ -4922,7 +4922,7 @@ restore_backup:
 
 	if (backup != NULL)
 	{
-	    struct stat st;
+	    stat_T	st;
 
 	    /*
 	     * If the original file does not exist yet
@@ -5271,7 +5271,7 @@ msg_add_eol(void)
  * using the same timestamp but can't set the size.
  */
     static int
-check_mtime(buf_T *buf, struct stat *st)
+check_mtime(buf_T *buf, stat_T *st)
 {
     if (buf->b_mtime_read != 0
 	    && time_differs((long)st->st_mtime, buf->b_mtime_read))
@@ -6453,7 +6453,7 @@ vim_rename(char_u *from, char_u *to)
 #ifdef AMIGA
     BPTR	flock;
 #endif
-    struct stat	st;
+    stat_T	st;
     long	perm;
 #ifdef HAVE_ACL
     vim_acl_T	acl;		/* ACL from original file */
@@ -6481,7 +6481,7 @@ vim_rename(char_u *from, char_u *to)
 
 #ifdef UNIX
     {
-	struct stat	st_to;
+	stat_T	st_to;
 
 	/* It's possible for the source and destination to be the same file.
 	 * This happens when "from" and "to" differ in case and are on a FAT32
@@ -6780,7 +6780,7 @@ buf_check_timestamp(
     buf_T	*buf,
     int		focus UNUSED)	/* called for GUI focus event */
 {
-    struct stat	st;
+    stat_T	st;
     int		stat_res;
     int		retval = 0;
     char_u	*path;
@@ -7221,7 +7221,7 @@ buf_reload(buf_T *buf, int orig_mode)
 }
 
     void
-buf_store_time(buf_T *buf, struct stat *st, char_u *fname UNUSED)
+buf_store_time(buf_T *buf, stat_T *st, char_u *fname UNUSED)
 {
     buf->b_mtime = (long)st->st_mtime;
     buf->b_orig_size = st->st_size;
@@ -7361,7 +7361,7 @@ vim_tempname(
     static char	*(tempdirs[]) = {TEMPDIRNAMES};
     int		i;
 # ifndef EEXIST
-    struct stat	st;
+    stat_T	st;
 # endif
 
     /*
diff --git a/src/gui.c b/src/gui.c
--- a/src/gui.c
+++ b/src/gui.c
@@ -571,7 +571,7 @@ gui_init(void)
 	    {
 #ifdef UNIX
 		{
-		    struct stat s;
+		    stat_T s;
 
 		    /* if ".gvimrc" file is not owned by user, set 'secure'
 		     * mode */
diff --git a/src/gui_at_fs.c b/src/gui_at_fs.c
--- a/src/gui_at_fs.c
+++ b/src/gui_at_fs.c
@@ -183,7 +183,7 @@ static void SFclearList(int n, int doScr
 static void SFbuttonPressList(Widget w, int n, XButtonPressedEvent *event);
 static void SFbuttonReleaseList(Widget w, int n, XButtonReleasedEvent *event);
 static void SFdirModTimer(XtPointer cl, XtIntervalId *id);
-static char SFstatChar(struct stat *statBuf);
+static char SFstatChar(stat_T *statBuf);
 static void SFdrawStrings(Window w, SFDir *dir, int from, int to);
 static int SFnewInvertEntry(int n, XMotionEvent *event);
 static void SFinvertEntry(int n);
@@ -873,7 +873,7 @@ static int SFcheckDir(int n, SFDir *dir)
     static int
 SFcheckDir(int n, SFDir *dir)
 {
-    struct stat	statBuf;
+    stat_T	statBuf;
     int		i;
 
     if ((!mch_stat(".", &statBuf)) && (statBuf.st_mtime != dir->mtime))
@@ -943,7 +943,7 @@ SFcheckFiles(SFDir *dir)
     int		i;
     char	*str;
     int		last;
-    struct stat	statBuf;
+    stat_T	statBuf;
 
     result = 0;
 
@@ -1017,7 +1017,7 @@ SFdirModTimer(XtPointer cl UNUSED, XtInt
 /* Return a single character describing what kind of file STATBUF is.  */
 
     static char
-SFstatChar(struct stat *statBuf)
+SFstatChar(stat_T *statBuf)
 {
     if (S_ISDIR (statBuf->st_mode))
 	return '/';
@@ -1313,13 +1313,13 @@ SFdeleteEntry(SFDir *dir, SFEntry *entry
 #endif
 }
 
-static void SFwriteStatChar(char *name, int last, struct stat *statBuf);
+static void SFwriteStatChar(char *name, int last, stat_T *statBuf);
 
     static void
 SFwriteStatChar(
     char	*name,
     int		last,
-    struct stat	*statBuf)
+    stat_T	*statBuf)
 {
     name[last] = SFstatChar(statBuf);
 }
@@ -1329,7 +1329,7 @@ static int SFstatAndCheck(SFDir *dir, SF
     static int
 SFstatAndCheck(SFDir *dir, SFEntry *entry)
 {
-    struct stat	statBuf;
+    stat_T	statBuf;
     char	save;
     int		last;
 
@@ -2059,7 +2059,7 @@ SFgetDir(
     char		*str;
     int			len;
     int			maxChars;
-    struct stat		statBuf;
+    stat_T		statBuf;
 
     maxChars = strlen(dir->dir) - 1;
 
diff --git a/src/if_cscope.c b/src/if_cscope.c
--- a/src/if_cscope.c
+++ b/src/if_cscope.c
@@ -42,7 +42,7 @@ static int	    cs_find_common(char *opt,
 static int	    cs_help(exarg_T *eap);
 static void	    clear_csinfo(int i);
 static int	    cs_insert_filelist(char *, char *, char *,
-			struct stat *);
+			stat_T *);
 static int	    cs_kill(exarg_T *eap);
 static void	    cs_kill_execute(int, char *);
 static cscmd_T *    cs_lookup_cmd(exarg_T *eap);
@@ -520,7 +520,7 @@ cs_add_common(
     char *arg2,	    /* prepend path - may contain environment variables */
     char *flags)
 {
-    struct stat statbuf;
+    stat_T	statbuf;
     int		ret;
     char	*fname = NULL;
     char	*fname2 = NULL;
@@ -547,7 +547,7 @@ cs_add_common(
     fname = (char *)vim_strnsave((char_u *)fname, len);
     vim_free(fbuf);
 #endif
-    ret = stat(fname, &statbuf);
+    ret = mch_stat(fname, &statbuf);
     if (ret < 0)
     {
 staterr:
@@ -559,13 +559,13 @@ staterr:
     /* get the prepend path (arg2), expand it, and try to stat it */
     if (arg2 != NULL)
     {
-	struct stat statbuf2;
+	stat_T	    statbuf2;
 
 	if ((ppath = (char *)alloc(MAXPATHL + 1)) == NULL)
 	    goto add_err;
 
 	expand_env((char_u *)arg2, (char_u *)ppath, MAXPATHL);
-	ret = stat(ppath, &statbuf2);
+	ret = mch_stat(ppath, &statbuf2);
 	if (ret < 0)
 	    goto staterr;
     }
@@ -592,7 +592,7 @@ staterr:
 	else
 	    (void)sprintf(fname2, "%s/%s", fname, CSCOPE_DBFILE);
 
-	ret = stat(fname2, &statbuf);
+	ret = mch_stat(fname2, &statbuf);
 	if (ret < 0)
 	{
 	    if (p_csverbose)
@@ -1414,7 +1414,7 @@ cs_insert_filelist(
     char *fname,
     char *ppath,
     char *flags,
-    struct stat *sb UNUSED)
+    stat_T *sb UNUSED)
 {
     short	i, j;
 #ifndef UNIX
diff --git a/src/main.c b/src/main.c
--- a/src/main.c
+++ b/src/main.c
@@ -3159,7 +3159,7 @@ process_env(
     static int
 file_owned(char *fname)
 {
-    struct stat s;
+    stat_T	s;
 # ifdef UNIX
     uid_t	uid = getuid();
 # else	 /* VMS */
diff --git a/src/memfile.c b/src/memfile.c
--- a/src/memfile.c
+++ b/src/memfile.c
@@ -1252,7 +1252,7 @@ mf_do_open(
     int		flags)		/* flags for open() */
 {
 #ifdef HAVE_LSTAT
-    struct stat sb;
+    stat_T	sb;
 #endif
 
     mfp->mf_fname = fname;
diff --git a/src/memline.c b/src/memline.c
--- a/src/memline.c
+++ b/src/memline.c
@@ -980,7 +980,7 @@ ml_upd_block0(buf_T *buf, upd_block0_T w
     static void
 set_b0_fname(ZERO_BL *b0p, buf_T *buf)
 {
-    struct stat	st;
+    stat_T	st;
 
     if (buf->b_ffname == NULL)
 	b0p->b0_fname[0] = NUL;
@@ -1121,7 +1121,7 @@ ml_recover(void)
     infoptr_T	*ip;
     blocknr_T	bnum;
     int		page_count;
-    struct stat	org_stat, swp_stat;
+    stat_T	org_stat, swp_stat;
     int		len;
     int		directly;
     linenr_T	lnum;
@@ -1915,7 +1915,7 @@ recover_names(
 	 */
 	if (*dirp == NUL && file_count + num_files == 0 && fname != NULL)
 	{
-	    struct stat	    st;
+	    stat_T	    st;
 	    char_u	    *swapname;
 
 	    swapname = modname(fname_res,
@@ -2056,7 +2056,7 @@ static int process_still_running;
     static time_t
 swapfile_info(char_u *fname)
 {
-    struct stat	    st;
+    stat_T	    st;
     int		    fd;
     struct block0   b0;
     time_t	    x = (time_t)0;
@@ -2278,7 +2278,7 @@ end:
 ml_sync_all(int check_file, int check_char)
 {
     buf_T		*buf;
-    struct stat		st;
+    stat_T		st;
 
     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
     {
@@ -4048,7 +4048,7 @@ attention_message(
     buf_T   *buf,	/* buffer being edited */
     char_u  *fname)	/* swap file name */
 {
-    struct stat st;
+    stat_T	st;
     time_t	x, sx;
     char	*p;
 
@@ -4229,7 +4229,7 @@ findswapname(
 	{
 	    char_u	    *tail;
 	    char_u	    *fname2;
-	    struct stat	    s1, s2;
+	    stat_T	    s1, s2;
 	    int		    f1, f2;
 	    int		    created1 = FALSE, created2 = FALSE;
 	    int		    same = FALSE;
@@ -4318,7 +4318,7 @@ findswapname(
 	if (mch_getperm(fname) < 0)	/* it does not exist */
 	{
 #ifdef HAVE_LSTAT
-	    struct stat sb;
+	    stat_T	sb;
 
 	    /*
 	     * Extra security check: When a swap file is a symbolic link, this
@@ -4687,7 +4687,7 @@ fnamecmp_ino(
     char_u	*fname_s,	    /* file name from swap file */
     long	ino_block0)
 {
-    struct stat	st;
+    stat_T	st;
     ino_t	ino_c = 0;	    /* ino of current file */
     ino_t	ino_s;		    /* ino of file from swap file */
     char_u	buf_c[MAXPATHL];    /* full path of fname_c */
diff --git a/src/misc1.c b/src/misc1.c
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -4069,7 +4069,7 @@ expand_env_esc(
 		{
 		    char_u	test[MAXPATHL], paths[MAXPATHL];
 		    char_u	*path, *next_path, *ptr;
-		    struct stat	st;
+		    stat_T	st;
 
 		    STRCPY(paths, USER_HOME);
 		    next_path = paths;
@@ -4765,7 +4765,7 @@ fullpathcmp(
     char_u	    exp1[MAXPATHL];
     char_u	    full1[MAXPATHL];
     char_u	    full2[MAXPATHL];
-    struct stat	    st1, st2;
+    stat_T	    st1, st2;
     int		    r1, r2;
 
     expand_env(s1, exp1, MAXPATHL);
@@ -9513,7 +9513,7 @@ preserve_exit(void)
     int
 vim_fexists(char_u *fname)
 {
-    struct stat st;
+    stat_T st;
 
     if (mch_stat((char *)fname, &st))
 	return FALSE;
@@ -10277,7 +10277,7 @@ unix_expandpath(
 		}
 		else
 		{
-		    struct stat sb;
+		    stat_T  sb;
 
 		    /* no more wildcards, check if there is a match */
 		    /* remove backslashes for the remaining components only */
@@ -11032,7 +11032,7 @@ addfile(
 {
     char_u	*p;
     int		isdir;
-    struct stat sb;
+    stat_T	sb;
 
     /* if the file/dir/link doesn't exist, may not add it */
     if (!(flags & EW_NOTFOUND) && ((flags & EW_ALLLINKS)
diff --git a/src/misc2.c b/src/misc2.c
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -5053,7 +5053,7 @@ ff_check_visited(
 {
     ff_visited_T	*vp;
 #ifdef UNIX
-    struct stat		st;
+    stat_T		st;
     int			url = FALSE;
 #endif
 
diff --git a/src/netbeans.c b/src/netbeans.c
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -253,7 +253,7 @@ getConnInfo(char *file, char **host, cha
     char_u *lp;
     char_u *nlp;
 #ifdef UNIX
-    struct stat	st;
+    stat_T	st;
 
     /*
      * For Unix only accept the file when it's not accessible by others.
@@ -1733,7 +1733,7 @@ nb_do_cmd(
 		buf->bufp->b_changed = TRUE;
 	    else
 	    {
-		struct stat	st;
+		stat_T	st;
 
 		/* Assume NetBeans stored the file.  Reset the timestamp to
 		 * avoid "file changed" warnings. */
diff --git a/src/os_mswin.c b/src/os_mswin.c
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -498,6 +498,18 @@ slash_adjust(char_u *p)
     }
 }
 
+/* Use 64-bit stat functions if available. */
+#ifdef HAVE_STAT64
+# undef stat
+# undef _stat
+# undef _wstat
+# undef _fstat
+# define stat _stat64
+# define _stat _stat64
+# define _wstat _wstat64
+# define _fstat _fstat64
+#endif
+
 #if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__)
 # define OPEN_OH_ARGTYPE intptr_t
 #else
@@ -505,7 +517,7 @@ slash_adjust(char_u *p)
 #endif
 
     static int
-stat_symlink_aware(const char *name, struct stat *stp)
+stat_symlink_aware(const char *name, stat_T *stp)
 {
 #if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__MINGW32__)
     /* Work around for VC12 or earlier (and MinGW). stat() can't handle
@@ -544,7 +556,7 @@ stat_symlink_aware(const char *name, str
 	    int	    fd, n;
 
 	    fd = _open_osfhandle((OPEN_OH_ARGTYPE)h, _O_RDONLY);
-	    n = _fstat(fd, (struct _stat*)stp);
+	    n = _fstat(fd, (struct _stat *)stp);
 	    if ((n == 0) && (attr & FILE_ATTRIBUTE_DIRECTORY))
 		stp->st_mode = (stp->st_mode & ~S_IFREG) | S_IFDIR;
 	    _close(fd);
@@ -557,7 +569,7 @@ stat_symlink_aware(const char *name, str
 
 #ifdef FEAT_MBYTE
     static int
-wstat_symlink_aware(const WCHAR *name, struct _stat *stp)
+wstat_symlink_aware(const WCHAR *name, stat_T *stp)
 {
 # if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__MINGW32__)
     /* Work around for VC12 or earlier (and MinGW). _wstat() can't handle
@@ -597,7 +609,7 @@ wstat_symlink_aware(const WCHAR *name, s
 	    int	    fd;
 
 	    fd = _open_osfhandle((OPEN_OH_ARGTYPE)h, _O_RDONLY);
-	    n = _fstat(fd, stp);
+	    n = _fstat(fd, (struct _stat *)stp);
 	    if ((n == 0) && (attr & FILE_ATTRIBUTE_DIRECTORY))
 		stp->st_mode = (stp->st_mode & ~S_IFREG) | S_IFDIR;
 	    _close(fd);
@@ -605,7 +617,7 @@ wstat_symlink_aware(const WCHAR *name, s
 	}
     }
 # endif
-    return _wstat(name, stp);
+    return _wstat(name, (struct _stat *)stp);
 }
 #endif
 
@@ -613,7 +625,7 @@ wstat_symlink_aware(const WCHAR *name, s
  * stat() can't handle a trailing '/' or '\', remove it first.
  */
     int
-vim_stat(const char *name, struct stat *stp)
+vim_stat(const char *name, stat_T *stp)
 {
 #ifdef FEAT_MBYTE
     /* WinNT and later can use _MAX_PATH wide characters for a pathname, which
@@ -658,7 +670,7 @@ vim_stat(const char *name, struct stat *
 
 	if (wp != NULL)
 	{
-	    n = wstat_symlink_aware(wp, (struct _stat *)stp);
+	    n = wstat_symlink_aware(wp, stp);
 	    vim_free(wp);
 	    if (n >= 0 || g_PlatformId == VER_PLATFORM_WIN32_NT)
 		return n;
diff --git a/src/os_win32.c b/src/os_win32.c
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -3065,7 +3065,7 @@ mch_dirname(
     long
 mch_getperm(char_u *name)
 {
-    struct stat st;
+    stat_T	st;
     int		n;
 
     n = mch_stat(name, &st);
diff --git a/src/proto/fileio.pro b/src/proto/fileio.pro
--- a/src/proto/fileio.pro
+++ b/src/proto/fileio.pro
@@ -20,7 +20,7 @@ int vim_rename(char_u *from, char_u *to)
 int check_timestamps(int focus);
 int buf_check_timestamp(buf_T *buf, int focus);
 void buf_reload(buf_T *buf, int orig_mode);
-void buf_store_time(buf_T *buf, struct stat *st, char_u *fname);
+void buf_store_time(buf_T *buf, stat_T *st, char_u *fname);
 void write_lnum_adjust(linenr_T offset);
 int delete_recursive(char_u *name);
 void vim_deltempdir(void);
diff --git a/src/proto/os_mswin.pro b/src/proto/os_mswin.pro
--- a/src/proto/os_mswin.pro
+++ b/src/proto/os_mswin.pro
@@ -9,7 +9,7 @@ int mch_can_restore_icon(void);
 int mch_FullName(char_u *fname, char_u *buf, int len, int force);
 int mch_isFullName(char_u *fname);
 void slash_adjust(char_u *p);
-int vim_stat(const char *name, struct stat *stp);
+int vim_stat(const char *name, stat_T *stp);
 void mch_settmode(int tmode);
 int mch_get_shellsize(void);
 void mch_set_shellsize(void);
diff --git a/src/pty.c b/src/pty.c
--- a/src/pty.c
+++ b/src/pty.c
@@ -247,7 +247,7 @@ OpenPTY(char **ttyn)
 OpenPTY(char **ttyn)
 {
     int		f;
-    struct stat buf;
+    stat_T	buf;
     /* used for opening a new pty-pair: */
     static char TtyName[32];
 
diff --git a/src/quickfix.c b/src/quickfix.c
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -2896,7 +2896,7 @@ get_mef_name(void)
     static int	start = -1;
     static int	off = 0;
 #ifdef HAVE_LSTAT
-    struct stat	sb;
+    stat_T	sb;
 #endif
 
     if (*p_mef == NUL)
diff --git a/src/spell.c b/src/spell.c
--- a/src/spell.c
+++ b/src/spell.c
@@ -9035,7 +9035,7 @@ mkspell(
     afffile_T	*(afile[8]);
     int		i;
     int		len;
-    struct stat	st;
+    stat_T	st;
     int		error = FALSE;
     spellinfo_T spin;
 
diff --git a/src/tag.c b/src/tag.c
--- a/src/tag.c
+++ b/src/tag.c
@@ -3508,7 +3508,7 @@ simplify_filename(char_u *filename)
 	    {
 		int		do_strip = FALSE;
 		char_u		saved_char;
-		struct stat	st;
+		stat_T		st;
 
 		/* Don't strip for an erroneous file name. */
 		if (!stripping_disabled)
@@ -3553,7 +3553,7 @@ simplify_filename(char_u *filename)
 #ifdef UNIX
 			if (do_strip)
 			{
-			    struct stat	new_st;
+			    stat_T	new_st;
 
 			    /* On Unix, the check for the unstripped file name
 			     * above works also for a symbolic link pointing to
diff --git a/src/undo.c b/src/undo.c
--- a/src/undo.c
+++ b/src/undo.c
@@ -776,7 +776,7 @@ u_get_undo_file_name(char_u *buf_ffname,
     char_u	*undo_file_name = NULL;
     int		dir_len;
     char_u	*p;
-    struct stat st;
+    stat_T	st;
     char_u	*ffname = buf_ffname;
 #ifdef HAVE_READLINK
     char_u	fname_buf[MAXPATHL];
@@ -1520,8 +1520,8 @@ u_write_undo(
     int		write_ok = FALSE;
 #ifdef UNIX
     int		st_old_valid = FALSE;
-    struct stat	st_old;
-    struct stat	st_new;
+    stat_T	st_old;
+    stat_T	st_new;
 #endif
     bufinfo_T	bi;
 
@@ -1802,8 +1802,8 @@ u_read_undo(char_u *name, char_u *hash, 
     int		*uhp_table_used;
 #endif
 #ifdef UNIX
-    struct stat	st_orig;
-    struct stat	st_undo;
+    stat_T	st_orig;
+    stat_T	st_undo;
 #endif
     bufinfo_T	bi;
 
diff --git a/src/vim.h b/src/vim.h
--- a/src/vim.h
+++ b/src/vim.h
@@ -2008,17 +2008,12 @@ typedef int sock_T;
 # endif
 #endif
 
-/* Use 64-bit stat functions if available. */
-#if ((defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__)) \
-					&& !defined(IN_PERL_FILE)
-# undef stat
-# undef _stat
-# undef _wstat
-# undef _fstat
-# define stat _stat64
-# define _stat _stat64
-# define _wstat _wstat64
-# define _fstat _fstat64
+/* Use 64-bit stat structure if available. */
+#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__)
+# define HAVE_STAT64
+typedef struct _stat64 stat_T;
+#else
+typedef struct stat stat_T;
 #endif
 
 #include "ex_cmds.h"	    /* Ex command defines */
# HG changeset patch
# Parent 7656647da44ed09b242c32cf1d95c9d4ca0df086
# Parent  4ed5969218754d7de671e1b741a83eeee0b0ffc7

diff --git a/src/Makefile b/src/Makefile
--- a/src/Makefile
+++ b/src/Makefile
@@ -1998,6 +1998,7 @@ test_arglist \
 	test_searchpos \
 	test_set \
 	test_sort \
+	test_stat \
 	test_syntax \
 	test_undolevels \
 	test_unlet \
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -176,6 +176,7 @@ NEW_TESTS = test_arglist.res \
 	    test_langmap.res \
 	    test_perl.res \
 	    test_quickfix.res \
+	    test_stat.res \
 	    test_syntax.res \
 	    test_viminfo.res \
 	    test_viml.res \
diff --git a/src/testdir/test_stat.vim b/src/testdir/test_stat.vim
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_stat.vim
@@ -0,0 +1,64 @@
+" Tests for stat functions and checktime
+
+func Test_existent_file()
+  let fname='Xtest.tmp'
+
+  let ts=localtime()
+  sleep 1
+  let fl=['Hello World!']
+  call writefile(fl, fname)
+  let tf=getftime(fname)
+  sleep 1
+  let te=localtime()
+
+  call assert_true(ts <= tf && tf <= te)
+  call assert_equal(strlen(fl[0] . "\n"), getfsize(fname))
+  call assert_equal('file', getftype(fname))
+  call assert_equal('rw-', getfperm(fname)[0:2])
+endfunc
+
+func Test_existent_directory()
+  let dname='.'
+
+  call assert_equal(0, getfsize(dname))
+  call assert_equal('dir', getftype(dname))
+  call assert_equal('rwx', getfperm(dname)[0:2])
+endfunc
+
+func Test_checktime()
+  let fname='Xtest.tmp'
+
+  let fl=['Hello World!']
+  call writefile(fl, fname)
+  set autoread
+  exec 'e' fname
+  sleep 2
+  let fl=readfile(fname)
+  let fl[0] .= ' - checktime'
+  call writefile(fl, fname)
+  checktime
+  call assert_equal(fl[0], getline(1))
+endfunc
+
+func Test_nonexistent_file()
+  let fname='Xtest.tmp'
+
+  call delete(fname)
+  call assert_equal(-1, getftime(fname))
+  call assert_equal(-1, getfsize(fname))
+  call assert_equal('', getftype(fname))
+  call assert_equal('', getfperm(fname))
+endfunc
+
+func Test_win32_symlink_dir()
+  " On Windows, non-admin users cannot create symlinks.
+  " So we use an existing symlink for this test.
+  if has('win32')
+    " Check if 'C:\Users\All Users' is a symlink to a directory.
+    let res=system('dir C:\Users /a')
+    if match(res, '\C<SYMLINKD> *All Users') >= 0
+      " Get the filetype of the symlink.
+      call assert_equal('dir', getftype('C:\Users\All Users'))
+    endif
+  endif
+endfunc
# HG changeset patch
# Parent  07f11de5efca36ddf3198a0d87c6becfd04cb783

diff --git a/src/testdir/test_largefile.vim b/src/testdir/test_largefile.vim
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_largefile.vim
@@ -0,0 +1,28 @@
+" Tests for large files
+
+func Test_largefile()
+  let fname='Xlarge.txt'
+
+  call delete(fname)
+  exe "e" fname
+  " Make sure that a line break is 1 byte (LF).
+  set ff=unix
+  set undolevels=-1
+  " Input 99 'A's. The line becomes 100 bytes including a line break.
+  exe "normal 99iA\<Esc>"
+  yank
+  " Put 39,999,999 times. The file becomes 4,000,000,000 bytes.
+  normal 39999999p
+  " Moving around in the file randomly.
+  normal G
+  normal 10%
+  normal 90%
+  normal 50%
+  normal gg
+  w
+  " Check if the file size is larger than 2^31 - 1 bytes.
+  " Note that getfsize() returns -2 if a Number is 32 bits.
+  let fsize=getfsize(fname)
+  call assert_true(fsize > 2147483647 || fsize == -2)
+  "call delete(fname)
+endfunc

Raspunde prin e-mail lui