From: Gurusamy Sarathy Date: Wed, 18 Dec 2002 02:08:12 +0000 (+0000) Subject: windows: support for large files X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=4a9d61009ab1e3df94ef4ecfcc453c9ce73010a4;p=p5sagit%2Fp5-mst-13.2.git windows: support for large files note that this change will break binary compatibility with the default 5.8.0 build options; nevertheless I think it is worth having in 5.8.1 (people who want the compatibility can disable the option in the makefile) p4raw-id: //depot/perl@18327 --- diff --git a/ext/Devel/DProf/DProf.xs b/ext/Devel/DProf/DProf.xs index 3525a27..78ea3c9 100644 --- a/ext/Devel/DProf/DProf.xs +++ b/ext/Devel/DProf/DProf.xs @@ -84,7 +84,7 @@ typedef struct { U32 dprof_ticks; char* out_file_name; /* output file (defaults to tmon.out) */ PerlIO* fp; /* pointer to tmon.out file */ - long TIMES_LOCATION; /* Where in the file to store the time totals */ + Off_t TIMES_LOCATION; /* Where in the file to store the time totals */ int SAVE_STACK; /* How much data to buffer until end of run */ int prof_pid; /* pid of profiled process */ struct tms prof_start; diff --git a/ext/POSIX/POSIX.xs b/ext/POSIX/POSIX.xs index 9a4fc02..519f741 100644 --- a/ext/POSIX/POSIX.xs +++ b/ext/POSIX/POSIX.xs @@ -1374,11 +1374,17 @@ dup2(fd1, fd2) int fd1 int fd2 -SysRetLong +SV * lseek(fd, offset, whence) int fd Off_t offset int whence + CODE: + Off_t pos = PerlLIO_lseek(fd, offset, whence); + RETVAL = sizeof(Off_t) > sizeof(IV) + ? newSVnv((NV)pos) : newSViv((IV)pos); + OUTPUT: + RETVAL SysRet nice(incr) diff --git a/ext/PerlIO/scalar/scalar.xs b/ext/PerlIO/scalar/scalar.xs index 7bcee57..d92ef83 100644 --- a/ext/PerlIO/scalar/scalar.xs +++ b/ext/PerlIO/scalar/scalar.xs @@ -105,10 +105,10 @@ SSize_t PerlIOScalar_unread(pTHX_ PerlIO * f, const void *vbuf, Size_t count) { PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar); - char *dst = SvGROW(s->var, s->posn + count); + char *dst = SvGROW(s->var, (STRLEN)s->posn + count); Move(vbuf, dst + s->posn, count, char); s->posn += count; - SvCUR_set(s->var, s->posn); + SvCUR_set(s->var, (STRLEN)s->posn); SvPOK_on(s->var); return count; } @@ -128,7 +128,7 @@ PerlIOScalar_write(pTHX_ PerlIO * f, const void *vbuf, Size_t count) } else { if ((s->posn + count) > SvCUR(sv)) - dst = SvGROW(sv, s->posn + count); + dst = SvGROW(sv, (STRLEN)s->posn + count); else dst = SvPV_nolen(sv); offset = s->posn; @@ -136,7 +136,7 @@ PerlIOScalar_write(pTHX_ PerlIO * f, const void *vbuf, Size_t count) } Move(vbuf, dst + offset, count, char); if ((STRLEN) s->posn > SvCUR(sv)) - SvCUR_set(sv, s->posn); + SvCUR_set(sv, (STRLEN)s->posn); SvPOK_on(s->var); return count; } @@ -182,7 +182,7 @@ PerlIOScalar_get_cnt(pTHX_ PerlIO * f) if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) { PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar); if (SvCUR(s->var) > (STRLEN) s->posn) - return SvCUR(s->var) - s->posn; + return SvCUR(s->var) - (STRLEN)s->posn; else return 0; } diff --git a/ext/PerlIO/via/via.xs b/ext/PerlIO/via/via.xs index d454678..524d24a 100644 --- a/ext/PerlIO/via/via.xs +++ b/ext/PerlIO/via/via.xs @@ -350,7 +350,8 @@ IV PerlIOVia_seek(pTHX_ PerlIO * f, Off_t offset, int whence) { PerlIOVia *s = PerlIOSelf(f, PerlIOVia); - SV *offsv = sv_2mortal(newSViv(offset)); + SV *offsv = sv_2mortal(sizeof(Off_t) > sizeof(IV) + ? newSVnv((NV)offset) : newSViv((IV)offset)); SV *whsv = sv_2mortal(newSViv(whence)); SV *result = PerlIOVia_method(aTHX_ f, MYMethod(SEEK), G_SCALAR, offsv, whsv, @@ -364,7 +365,9 @@ PerlIOVia_tell(pTHX_ PerlIO * f) PerlIOVia *s = PerlIOSelf(f, PerlIOVia); SV *result = PerlIOVia_method(aTHX_ f, MYMethod(TELL), G_SCALAR, Nullsv); - return (result) ? (Off_t) SvIV(result) : (Off_t) - 1; + return (result) + ? (SvNOK(result) ? (Off_t)SvNV(result) : (Off_t)SvIV(result)) + : (Off_t) - 1; } SSize_t diff --git a/iperlsys.h b/iperlsys.h index c82ffa7..a712237 100644 --- a/iperlsys.h +++ b/iperlsys.h @@ -598,7 +598,7 @@ typedef int (*LPLIOAccess)(struct IPerlLIO*, const char*, int); typedef int (*LPLIOChmod)(struct IPerlLIO*, const char*, int); typedef int (*LPLIOChown)(struct IPerlLIO*, const char*, uid_t, gid_t); -typedef int (*LPLIOChsize)(struct IPerlLIO*, int, long); +typedef int (*LPLIOChsize)(struct IPerlLIO*, int, Off_t); typedef int (*LPLIOClose)(struct IPerlLIO*, int); typedef int (*LPLIODup)(struct IPerlLIO*, int); typedef int (*LPLIODup2)(struct IPerlLIO*, int, int); diff --git a/pp_sys.c b/pp_sys.c index 472f041..cd5bfec 100644 --- a/pp_sys.c +++ b/pp_sys.c @@ -2838,7 +2838,7 @@ PP(pp_stat) PUSHs(sv_2mortal(newSVpvn("", 0))); #endif #if Off_t_size > IVSIZE - PUSHs(sv_2mortal(newSVnv(PL_statcache.st_size))); + PUSHs(sv_2mortal(newSVnv((NV)PL_statcache.st_size))); #else PUSHs(sv_2mortal(newSViv(PL_statcache.st_size))); #endif diff --git a/win32/Makefile b/win32/Makefile index 901ff0c..bba77a9 100644 --- a/win32/Makefile +++ b/win32/Makefile @@ -74,11 +74,17 @@ USE_IMP_SYS = define USE_PERLIO = define # +# Comment this out if you don't want to enable large file support for +# some reason. Should normally only be changed to maintain compatibility +# with an older release of perl. +USE_LARGE_FILES = define + +# # uncomment one of the following lines if you are using either # Visual C++ 2.x or Visual C++ 6.x (aka Visual Studio 98) # #CCTYPE = MSVC20 -#CCTYPE = MSVC60 +CCTYPE = MSVC60 # # uncomment next line if you want debug version of perl (big,slow) @@ -216,6 +222,10 @@ USE_IMP_SYS = undef USE_PERLIO = undef !ENDIF +!IF "$(USE_LARGE_FILES)" == "" +USE_LARGE_FILES = undef +!ENDIF + !IF "$(USE_PERLCRT)" == "" USE_PERLCRT = undef !ENDIF @@ -767,6 +777,7 @@ CFG_VARS = \ "useithreads=$(USE_ITHREADS)" \ "usemultiplicity=$(USE_MULTI)" \ "useperlio=$(USE_PERLIO)" \ + "uselargefiles=$(USE_LARGE_FILES)" \ "LINK_FLAGS=$(LINK_FLAGS:"=\")" \ "optimize=$(OPTIMIZE:"=\")" diff --git a/win32/config.bc b/win32/config.bc index 7d669ff..d8ac588 100644 --- a/win32/config.bc +++ b/win32/config.bc @@ -697,8 +697,8 @@ longsize='4' lp='' lpr='' ls='dir' -lseeksize='4' -lseektype='off_t' +lseeksize='8' +lseektype='__int64' mail='' mailx='' make='dmake' @@ -904,7 +904,7 @@ use64bitint='undef' usecrosscompile='undef' usedl='define' useithreads='undef' -uselargefiles='undef' +uselargefiles='define' uselongdouble='undef' usemorebits='undef' usemultiplicity='undef' diff --git a/win32/config.gc b/win32/config.gc index 141fb54..f603bee 100644 --- a/win32/config.gc +++ b/win32/config.gc @@ -697,8 +697,8 @@ longsize='4' lp='' lpr='' ls='dir' -lseeksize='4' -lseektype='off_t' +lseeksize='8' +lseektype='long long' mail='' mailx='' make='dmake' @@ -904,7 +904,7 @@ use64bitint='undef' usecrosscompile='undef' usedl='define' useithreads='undef' -uselargefiles='undef' +uselargefiles='define' uselongdouble='undef' usemorebits='undef' usemultiplicity='undef' diff --git a/win32/config.vc b/win32/config.vc index 89192be..3400eff 100644 --- a/win32/config.vc +++ b/win32/config.vc @@ -697,8 +697,8 @@ longsize='4' lp='' lpr='' ls='dir' -lseeksize='4' -lseektype='off_t' +lseeksize='8' +lseektype='__int64' mail='' mailx='' make='nmake' @@ -904,7 +904,7 @@ use64bitint='undef' usecrosscompile='undef' usedl='define' useithreads='undef' -uselargefiles='undef' +uselargefiles='define' uselongdouble='undef' usemorebits='undef' usemultiplicity='undef' diff --git a/win32/config.vc64 b/win32/config.vc64 index bc96988..ca88714 100644 --- a/win32/config.vc64 +++ b/win32/config.vc64 @@ -904,7 +904,7 @@ use64bitint='define' usecrosscompile='undef' usedl='define' useithreads='undef' -uselargefiles='undef' +uselargefiles='define' uselongdouble='undef' usemorebits='undef' usemultiplicity='undef' diff --git a/win32/config_H.bc b/win32/config_H.bc index f4fec85..8bcd5fb 100644 --- a/win32/config_H.bc +++ b/win32/config_H.bc @@ -2950,9 +2950,9 @@ /* Off_t_size: * This symbol holds the number of bytes used by the Off_t. */ -#define Off_t off_t /* type */ -#define LSEEKSIZE 4 /* size */ -#define Off_t_size 4 /* size */ +#define Off_t __int64 /* type */ +#define LSEEKSIZE 8 /* size */ +#define Off_t_size 8 /* size */ /* Free_t: * This variable contains the return type of free(). It is usually @@ -3445,7 +3445,7 @@ * should be used when available. */ #ifndef USE_LARGE_FILES -/*#define USE_LARGE_FILES /**/ +#define USE_LARGE_FILES /**/ #endif /* USE_LONG_DOUBLE: diff --git a/win32/config_H.gc b/win32/config_H.gc index 2422466..c9ce667 100644 --- a/win32/config_H.gc +++ b/win32/config_H.gc @@ -2950,9 +2950,9 @@ /* Off_t_size: * This symbol holds the number of bytes used by the Off_t. */ -#define Off_t off_t /* type */ -#define LSEEKSIZE 4 /* size */ -#define Off_t_size 4 /* size */ +#define Off_t long long /* type */ +#define LSEEKSIZE 8 /* size */ +#define Off_t_size 8 /* size */ /* Free_t: * This variable contains the return type of free(). It is usually @@ -3445,7 +3445,7 @@ * should be used when available. */ #ifndef USE_LARGE_FILES -/*#define USE_LARGE_FILES /**/ +#define USE_LARGE_FILES /**/ #endif /* USE_LONG_DOUBLE: diff --git a/win32/config_H.vc b/win32/config_H.vc index 8fcfb0f..c4ba4a5 100644 --- a/win32/config_H.vc +++ b/win32/config_H.vc @@ -2950,9 +2950,9 @@ /* Off_t_size: * This symbol holds the number of bytes used by the Off_t. */ -#define Off_t off_t /* type */ -#define LSEEKSIZE 4 /* size */ -#define Off_t_size 4 /* size */ +#define Off_t __int64 /* type */ +#define LSEEKSIZE 8 /* size */ +#define Off_t_size 8 /* size */ /* Free_t: * This variable contains the return type of free(). It is usually @@ -3445,7 +3445,7 @@ * should be used when available. */ #ifndef USE_LARGE_FILES -/*#define USE_LARGE_FILES /**/ +#define USE_LARGE_FILES /**/ #endif /* USE_LONG_DOUBLE: diff --git a/win32/config_H.vc64 b/win32/config_H.vc64 index 5f1ff0f..5572c26 100644 --- a/win32/config_H.vc64 +++ b/win32/config_H.vc64 @@ -3445,7 +3445,7 @@ * should be used when available. */ #ifndef USE_LARGE_FILES -/*#define USE_LARGE_FILES /**/ +#define USE_LARGE_FILES /**/ #endif /* USE_LONG_DOUBLE: diff --git a/win32/config_sh.PL b/win32/config_sh.PL index b31415d..3b76cd0 100644 --- a/win32/config_sh.PL +++ b/win32/config_sh.PL @@ -90,6 +90,11 @@ if (defined(&Win32::IsWin95) && Win32::IsWin95()) { $opt{d_link} = 'undef'; } +if ($opt{uselargefiles} ne 'define') { + $opt{lseeksize} = 4; + $opt{lseektype} = 'off_t'; +} + while (<>) { s/~([\w_]+)~/$opt{$1}/g; if (/^([\w_]+)=(.*)$/) { diff --git a/win32/makefile.mk b/win32/makefile.mk index 683cb42..723d5b2 100644 --- a/win32/makefile.mk +++ b/win32/makefile.mk @@ -73,7 +73,13 @@ USE_IMP_SYS *= define # then get a number of fails from make test i.e. bugs - complain to them not us ;-). # You will also be unable to take full advantage of perl5.8's support for multiple # encodings and may see lower IO performance. You have been warned. -USE_PERLIO = define +USE_PERLIO *= define + +# +# Comment this out if you don't want to enable large file support for +# some reason. Should normally only be changed to maintain compatibility +# with an older release of perl. +USE_LARGE_FILES *= define # # uncomment exactly one of the following @@ -233,6 +239,7 @@ USE_MULTI *= undef USE_ITHREADS *= undef USE_IMP_SYS *= undef USE_PERLIO *= undef +USE_LARGE_FILES *= undef USE_PERLCRT *= undef .IF "$(USE_IMP_SYS)$(USE_MULTI)" == "defineundef" @@ -813,7 +820,8 @@ CFG_VARS = \ useithreads=$(USE_ITHREADS) ~ \ usemultiplicity=$(USE_MULTI) ~ \ useperlio=$(USE_PERLIO) ~ \ - LINK_FLAGS=$(LINK_FLAGS:s/\/\\/) ~ \ + uselargefiles=$(USE_LARGE_FILES) ~ \ + LINK_FLAGS=$(LINK_FLAGS:s/\/\\/) ~ \ optimize=$(OPTIMIZE) # diff --git a/win32/perlhost.h b/win32/perlhost.h index 7926142..b68f5c7 100644 --- a/win32/perlhost.h +++ b/win32/perlhost.h @@ -939,9 +939,9 @@ PerlLIOChown(struct IPerlLIO* piPerl, const char *filename, uid_t owner, gid_t g } int -PerlLIOChsize(struct IPerlLIO* piPerl, int handle, long size) +PerlLIOChsize(struct IPerlLIO* piPerl, int handle, Off_t size) { - return chsize(handle, size); + return win32_chsize(handle, size); } int diff --git a/win32/win32.c b/win32/win32.c index 633dbbd..556d621 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -3073,6 +3073,55 @@ win32_setmode(int fd, int mode) return setmode(fd, mode); } +DllExport int +win32_chsize(int fd, Off_t size) +{ +#if defined(WIN64) || defined(USE_LARGE_FILES) + int retval = 0; + Off_t cur, end, extend; + + cur = win32_tell(fd); + if (cur < 0) + return -1; + end = win32_lseek(fd, 0, SEEK_END); + if (end < 0) + return -1; + extend = size - end; + if (extend == 0) { + /* do nothing */ + } + else if (extend > 0) { + /* must grow the file, padding with nulls */ + char b[4096]; + int oldmode = win32_setmode(fd, O_BINARY); + size_t count; + memset(b, '\0', sizeof(b)); + do { + count = extend >= sizeof(b) ? sizeof(b) : (size_t)extend; + count = win32_write(fd, b, count); + if (count < 0) { + retval = -1; + break; + } + } while ((extend -= count) > 0); + win32_setmode(fd, oldmode); + } + else { + /* shrink the file */ + win32_lseek(fd, size, SEEK_SET); + if (!SetEndOfFile((HANDLE)_get_osfhandle(fd))) { + errno = EACCES; + retval = -1; + } + } +finish: + win32_lseek(fd, cur, SEEK_SET); + return retval; +#else + return chsize(fd, size); +#endif +} + DllExport Off_t win32_lseek(int fd, Off_t offset, int origin) { diff --git a/win32/win32iop.h b/win32/win32iop.h index 52c59b4..e835b2e 100644 --- a/win32/win32iop.h +++ b/win32/win32iop.h @@ -77,6 +77,7 @@ DllExport PerlIO* win32_popenlist(const char *mode, IV narg, SV **args); DllExport int win32_pclose( PerlIO *pf); DllExport int win32_rename( const char *oname, const char *newname); DllExport int win32_setmode( int fd, int mode); +DllExport int win32_chsize(int fd, Off_t size); DllExport Off_t win32_lseek( int fd, Off_t offset, int origin); DllExport Off_t win32_tell( int fd); DllExport int win32_dup( int fd); @@ -236,6 +237,7 @@ END_EXTERN_C #define longpath(pth) win32_longpath(pth) #define rename(old,new) win32_rename(old,new) #define setmode(fd,mode) win32_setmode(fd,mode) +#define chsize(fd,sz) win32_chsize(fd,sz) #define lseek(fd,offset,orig) win32_lseek(fd,offset,orig) #define tell(fd) win32_tell(fd) #define dup(fd) win32_dup(fd)