[Patches] fix posixmodule for 64-bit systems (mainly Win64)

Trent Mick trentm@activestate.com
Thu, 1 Jun 2000 19:22:13 -0700


Discussion:

This patch fixes the posix module for large file support mainly on Win64,
although some general cleanup is done as well.

The changes are:
- abstract stat->STAT, fstat->FSTAT, and struct stat->STRUCT_STAT
  This is because stat() etc. are not the correct functions to use on Win64
  (nor maybe on other platforms?, if not then it is now trivial to select the
  appropriate one). On Win64 the appropriate system functions are _stati64(),
  etc.
- add _pystat_fromstructstat(), it builds the return tuple for the fstat
  system call. This functionality was being duplicated. As well the
  construction of the tuple was modified to ensure no overflow of the time_t
  elements (sizeof(time_t) > sizeof(long) on Win64).
- add overflow protection for the return values of posix_spawnv and
  posix_spawnve
- use the proper 64-bit capable lseek() on Win64
- use intptr_t instead of long where appropriate from Win32/64 blocks
  (sizeof(void*) > sizeof(long) on Win64)


Legal:

I confirm that, to the best of my knowledge and belief, this
contribution is free of any claims of third parties under
copyright, patent or other rights or interests ("claims").  To
the extent that I have any such claims, I hereby grant to CNRI a
nonexclusive, irrevocable, royalty-free, worldwide license to
reproduce, distribute, perform and/or display publicly, prepare
derivative versions, and otherwise use this contribution as part
of the Python software and its related documentation, or any
derivative versions thereof, at no cost to CNRI or its licensed
users, and to authorize others to do so.

I acknowledge that CNRI may, at its sole discretion, decide
whether or not to incorporate this contribution in the Python
software and its related documentation.  I further grant CNRI
permission to use my name and other identifying information
provided to CNRI by me for use in connection with the Python
software and its related documentation.


Patch (use 'patch -p8'):

*** /home/trentm/main/contrib/python/dist/src/Modules/posixmodule.c	Thu Jun  1 00:13:39 2000
--- /home/trentm/main/Apps/Perlium/Python/dist/src/Modules/posixmodule.c	Wed May 31 23:54:18 2000
***************
*** 284,289 ****
--- 283,300 ----
  #define USE_TMPNAM_R
  #endif
  
+ /* choose the appropriate stat and fstat functions and return structs */
+ #ifdef MS_WIN64
+ #	define STAT _stati64
+ #	define FSTAT _fstati64
+ #	define STRUCT_STAT struct _stati64
+ #else
+ #	define STAT stat
+ #	define FSTAT fstat
+ #	define STRUCT_STAT struct stat
+ #endif
+ 
+ 
  /* Return a dictionary corresponding to the POSIX environment table */
  
  #if !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
***************
*** 539,552 ****
  	return Py_None;
  }
  
  static PyObject *
  posix_do_stat(self, args, format, statfunc)
  	PyObject *self;
  	PyObject *args;
          char *format;
! 	int (*statfunc) Py_FPROTO((const char *, struct stat *));
  {
! 	struct stat st;
  	char *path;
  	int res;
  
--- 550,613 ----
  	return Py_None;
  }
  
+ 
+ 
+ /* pack a system stat C structure into the Python stat tuple 
+    (used by posix_stat() and posix_fstat()) */
+ static PyObject*
+ _pystat_fromstructstat(st)
+ 	STRUCT_STAT st;
+ {
+ 	PyObject *v = PyTuple_New(10);
+ 	if (v == NULL)
+ 		return NULL;
+ 
+ 	PyTuple_SetItem(v, 0, PyInt_FromLong((long)st.st_mode));
+ #ifdef HAVE_LARGEFILE_SUPPORT
+ 	PyTuple_SetItem(v, 1, PyLong_FromLongLong((LONG_LONG)st.st_ino));
+ #else
+ 	PyTuple_SetItem(v, 1, PyInt_FromLong((long)st.st_ino));
+ #endif
+ #if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
+ 	PyTuple_SetItem(v, 2, PyLong_FromLongLong((LONG_LONG)st.st_dev));
+ #else
+ 	PyTuple_SetItem(v, 2, PyInt_FromLong((long)st.st_dev));
+ #endif
+ 	PyTuple_SetItem(v, 3, PyInt_FromLong((long)st.st_nlink));
+ 	PyTuple_SetItem(v, 4, PyInt_FromLong((long)st.st_uid));
+ 	PyTuple_SetItem(v, 5, PyInt_FromLong((long)st.st_gid));
+ #ifdef HAVE_LARGEFILE_SUPPORT
+ 	PyTuple_SetItem(v, 6, PyLong_FromLongLong((LONG_LONG)st.st_size));
+ #else
+ 	PyTuple_SetItem(v, 6, PyInt_FromLong(st.st_size));
+ #endif
+ #if SIZEOF_TIME_T > SIZEOF_LONG
+ 	PyTuple_SetItem(v, 7, PyLong_FromLongLong((LONG_LONG)st.st_atime));
+ 	PyTuple_SetItem(v, 8, PyLong_FromLongLong((LONG_LONG)st.st_mtime));
+ 	PyTuple_SetItem(v, 9, PyLong_FromLongLong((LONG_LONG)st.st_ctime));
+ #else
+ 	PyTuple_SetItem(v, 7, PyInt_FromLong((long)st.st_atime));
+ 	PyTuple_SetItem(v, 8, PyInt_FromLong((long)st.st_mtime));
+ 	PyTuple_SetItem(v, 9, PyInt_FromLong((long)st.st_ctime));
+ #endif
+ 
+ 	if (PyErr_Occurred()) {
+ 		Py_DECREF(v);
+ 		return NULL;
+ 	}
+ 
+ 	return v;
+ }
+ 
+ 
  static PyObject *
  posix_do_stat(self, args, format, statfunc)
  	PyObject *self;
  	PyObject *args;
          char *format;
! 	int (*statfunc) Py_FPROTO((const char *, STRUCT_STAT *));
  {
! 	STRUCT_STAT st;
  	char *path;
  	int res;
  
***************
*** 585,615 ****
  	Py_END_ALLOW_THREADS
  	if (res != 0)
  		return posix_error_with_filename(path);
! #if !defined(HAVE_LARGEFILE_SUPPORT)
! 	return Py_BuildValue("(llllllllll)",
! 			     (long)st.st_mode,
! 			     (long)st.st_ino,
! 			     (long)st.st_dev,
! 			     (long)st.st_nlink,
! 			     (long)st.st_uid,
! 			     (long)st.st_gid,
! 			     (long)st.st_size,
! 			     (long)st.st_atime,
! 			     (long)st.st_mtime,
! 			     (long)st.st_ctime);
! #else
! 	return Py_BuildValue("(lLllllLlll)",
! 			     (long)st.st_mode,
! 			     (LONG_LONG)st.st_ino,
! 			     (long)st.st_dev,
! 			     (long)st.st_nlink,
! 			     (long)st.st_uid,
! 			     (long)st.st_gid,
! 			     (LONG_LONG)st.st_size,
! 			     (long)st.st_atime,
! 			     (long)st.st_mtime,
! 			     (long)st.st_ctime);
! #endif
  }
  
  
--- 646,653 ----
  	Py_END_ALLOW_THREADS
  	if (res != 0)
  		return posix_error_with_filename(path);
! 
! 	return _pystat_fromstructstat(st);
  }
  
  
***************
*** 1158,1164 ****
  	PyObject *self;
  	PyObject *args;
  {
! 	return posix_do_stat(self, args, "s:stat", stat);
  }
  
  
--- 1197,1203 ----
  	PyObject *self;
  	PyObject *args;
  {
! 	return posix_do_stat(self, args, "s:stat", STAT);
  }
  
  
***************
*** 1546,1551 ****
--- 1585,1591 ----
  	PyObject *argv;
  	char **argvlist;
  	int mode, i, argc;
+ 	intptr_t spawnval;
  	PyObject *(*getitem) Py_PROTO((PyObject *, int));
  
  	/* spawnv has three arguments: (mode, path, argv), where
***************
*** 1580,1593 ****
  
  	if (mode == _OLD_P_OVERLAY)
  		mode = _P_OVERLAY;
! 	i = _spawnv(mode, path, argvlist);
  
  	PyMem_DEL(argvlist);
  
! 	if (i == -1)
  		return posix_error();
  	else
! 		return Py_BuildValue("i", i);
  }
  
  
--- 1620,1637 ----
  
  	if (mode == _OLD_P_OVERLAY)
  		mode = _P_OVERLAY;
! 	spawnval = _spawnv(mode, path, argvlist);
  
  	PyMem_DEL(argvlist);
  
! 	if (spawnval == -1)
  		return posix_error();
  	else
! #if SIZEOF_LONG == SIZE_VOID_P
! 		return Py_BuildValue("l", spawnval);
! #else
! 		return Py_BuildValue("L", spawnval);
! #endif
  }
  
  
***************
*** 1611,1616 ****
--- 1655,1661 ----
  	char **envlist;
  	PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
  	int mode, i, pos, argc, envc;
+ 	intptr_t spawnval;
  	PyObject *(*getitem) Py_PROTO((PyObject *, int));
  
  	/* spawnve has four arguments: (mode, path, argv, env), where
***************
*** 1688,1698 ****
  
  	if (mode == _OLD_P_OVERLAY)
  		mode = _P_OVERLAY;
! 	i = _spawnve(mode, path, argvlist, envlist);
! 	if (i == -1)
  		(void) posix_error();
  	else
! 		res = Py_BuildValue("i", i);
  
   fail_2:
  	while (--envc >= 0)
--- 1733,1747 ----
  
  	if (mode == _OLD_P_OVERLAY)
  		mode = _P_OVERLAY;
! 	spawnval = _spawnve(mode, path, argvlist, envlist);
! 	if (spawnval == -1)
  		(void) posix_error();
  	else
! #if SIZEOF_LONG == SIZE_VOID_P
! 		res = Py_BuildValue("l", spawnval);
! #else
! 		res = Py_BuildValue("L", spawnval);
! #endif
  
   fail_2:
  	while (--envc >= 0)
***************
*** 2269,2275 ****
  #ifdef HAVE_LSTAT
  	return posix_do_stat(self, args, "s:lstat", lstat);
  #else /* !HAVE_LSTAT */
! 	return posix_do_stat(self, args, "s:lstat", stat);
  #endif /* !HAVE_LSTAT */
  }
  
--- 2318,2324 ----
  #ifdef HAVE_LSTAT
  	return posix_do_stat(self, args, "s:lstat", lstat);
  #else /* !HAVE_LSTAT */
! 	return posix_do_stat(self, args, "s:lstat", STAT);
  #endif /* !HAVE_LSTAT */
  }
  
***************
*** 2593,2599 ****
--- 2642,2652 ----
  	PyObject *args;
  {
  	int fd, how;
+ #ifdef MS_WIN64
+ 	LONG_LONG pos, res;
+ #else
  	off_t pos, res;
+ #endif
  	PyObject *posobj;
  	if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
  		return NULL;
***************
*** 2616,2622 ****
--- 2669,2679 ----
  		return NULL;
  
  	Py_BEGIN_ALLOW_THREADS
+ #ifdef MS_WIN64
+ 	res = _lseeki64(fd, pos, how);
+ #else
  	res = lseek(fd, pos, how);
+ #endif
  	Py_END_ALLOW_THREADS
  	if (res < 0)
  		return posix_error();
***************
*** 2690,2729 ****
  	PyObject *args;
  {
  	int fd;
! 	struct stat st;
  	int res;
  	if (!PyArg_ParseTuple(args, "i:fstat", &fd))
  		return NULL;
  	Py_BEGIN_ALLOW_THREADS
! 	res = fstat(fd, &st);
  	Py_END_ALLOW_THREADS
  	if (res != 0)
  		return posix_error();
! #if !defined(HAVE_LARGEFILE_SUPPORT)
! 	return Py_BuildValue("(llllllllll)",
! 			     (long)st.st_mode,
! 			     (long)st.st_ino,
! 			     (long)st.st_dev,
! 			     (long)st.st_nlink,
! 			     (long)st.st_uid,
! 			     (long)st.st_gid,
! 			     (long)st.st_size,
! 			     (long)st.st_atime,
! 			     (long)st.st_mtime,
! 			     (long)st.st_ctime);
! #else
! 	return Py_BuildValue("(lLllllLlll)",
! 			     (long)st.st_mode,
! 			     (LONG_LONG)st.st_ino,
! 			     (long)st.st_dev,
! 			     (long)st.st_nlink,
! 			     (long)st.st_uid,
! 			     (long)st.st_gid,
! 			     (LONG_LONG)st.st_size,
! 			     (long)st.st_atime,
! 			     (long)st.st_mtime,
! 			     (long)st.st_ctime);
! #endif
  }
  
  
--- 2747,2763 ----
  	PyObject *args;
  {
  	int fd;
! 	STRUCT_STAT st;
  	int res;
  	if (!PyArg_ParseTuple(args, "i:fstat", &fd))
  		return NULL;
  	Py_BEGIN_ALLOW_THREADS
! 	res = FSTAT(fd, &st);
  	Py_END_ALLOW_THREADS
  	if (res != 0)
  		return posix_error();
! 	
! 	return _pystat_fromstructstat(st);
  }
  
  
***************
*** 2804,2811 ****
  	Py_END_ALLOW_THREADS
  	if (!ok)
  		return posix_error();
! 	read_fd = _open_osfhandle((long)read, 0);
! 	write_fd = _open_osfhandle((long)write, 1);
  	return Py_BuildValue("(ii)", read_fd, write_fd);
  #endif /* MS_WIN32 */
  #endif
--- 2838,2845 ----
  	Py_END_ALLOW_THREADS
  	if (!ok)
  		return posix_error();
! 	read_fd = _open_osfhandle((intptr_t)read, 0);
! 	write_fd = _open_osfhandle((intptr_t)write, 1);
  	return Py_BuildValue("(ii)", read_fd, write_fd);
  #endif /* MS_WIN32 */
  #endif
***************
*** 3467,3475 ****
      }
      if (PyString_Check(arg)) {
          /* look up the value in the table using a binary search */
!         int lo = 0;
!         int hi = tablesize;
!         int cmp, mid;
          char *confname = PyString_AS_STRING(arg);
          while (lo < hi) {
              mid = (lo + hi) / 2;
--- 3501,3510 ----
      }
      if (PyString_Check(arg)) {
          /* look up the value in the table using a binary search */
!         size_t lo = 0;
! 		size_t mid;
!         size_t hi = tablesize;
!         int cmp;
          char *confname = PyString_AS_STRING(arg);
          while (lo < hi) {
              mid = (lo + hi) / 2;

-- 
Trent Mick
trentm@activestate.com