mercurial/osutil.c
changeset 27473 34a37a2e03e6
parent 26983 f9f2f29ce023
child 27877 f6d1e92fdf8c
equal deleted inserted replaced
27472:3dea4eae4eeb 27473:34a37a2e03e6
     9 
     9 
    10 #define _ATFILE_SOURCE
    10 #define _ATFILE_SOURCE
    11 #include <Python.h>
    11 #include <Python.h>
    12 #include <fcntl.h>
    12 #include <fcntl.h>
    13 #include <stdio.h>
    13 #include <stdio.h>
       
    14 #include <stdlib.h>
    14 #include <string.h>
    15 #include <string.h>
    15 #include <errno.h>
    16 #include <errno.h>
    16 
    17 
    17 #ifdef _WIN32
    18 #ifdef _WIN32
    18 #include <windows.h>
    19 #include <windows.h>
    19 #include <io.h>
    20 #include <io.h>
    20 #else
    21 #else
    21 #include <dirent.h>
    22 #include <dirent.h>
       
    23 #include <sys/socket.h>
    22 #include <sys/stat.h>
    24 #include <sys/stat.h>
    23 #include <sys/types.h>
    25 #include <sys/types.h>
    24 #include <unistd.h>
    26 #include <unistd.h>
    25 #endif
    27 #endif
    26 
    28 
   646 bail:
   648 bail:
   647 	Py_DECREF(stats);
   649 	Py_DECREF(stats);
   648 	return NULL;
   650 	return NULL;
   649 }
   651 }
   650 
   652 
       
   653 /*
       
   654  * recvfds() simply does not release GIL during blocking io operation because
       
   655  * command server is known to be single-threaded.
       
   656  */
       
   657 
       
   658 static ssize_t recvfdstobuf(int sockfd, int **rfds, void *cbuf, size_t cbufsize)
       
   659 {
       
   660 	char dummy[1];
       
   661 	struct iovec iov = {dummy, sizeof(dummy)};
       
   662 	struct msghdr msgh = {0};
       
   663 	struct cmsghdr *cmsg;
       
   664 
       
   665 	msgh.msg_iov = &iov;
       
   666 	msgh.msg_iovlen = 1;
       
   667 	msgh.msg_control = cbuf;
       
   668 	msgh.msg_controllen = (socklen_t)cbufsize;
       
   669 	if (recvmsg(sockfd, &msgh, 0) < 0)
       
   670 		return -1;
       
   671 
       
   672 	for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg;
       
   673 	     cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
       
   674 		if (cmsg->cmsg_level != SOL_SOCKET ||
       
   675 		    cmsg->cmsg_type != SCM_RIGHTS)
       
   676 			continue;
       
   677 		*rfds = (int *)CMSG_DATA(cmsg);
       
   678 		return (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
       
   679 	}
       
   680 
       
   681 	*rfds = cbuf;
       
   682 	return 0;
       
   683 }
       
   684 
       
   685 static PyObject *recvfds(PyObject *self, PyObject *args)
       
   686 {
       
   687 	int sockfd;
       
   688 	int *rfds = NULL;
       
   689 	ssize_t rfdscount, i;
       
   690 	char cbuf[256];
       
   691 	PyObject *rfdslist = NULL;
       
   692 
       
   693 	if (!PyArg_ParseTuple(args, "i", &sockfd))
       
   694 		return NULL;
       
   695 
       
   696 	rfdscount = recvfdstobuf(sockfd, &rfds, cbuf, sizeof(cbuf));
       
   697 	if (rfdscount < 0)
       
   698 		return PyErr_SetFromErrno(PyExc_OSError);
       
   699 
       
   700 	rfdslist = PyList_New(rfdscount);
       
   701 	if (!rfdslist)
       
   702 		goto bail;
       
   703 	for (i = 0; i < rfdscount; i++) {
       
   704 		PyObject *obj = PyInt_FromLong(rfds[i]);
       
   705 		if (!obj)
       
   706 			goto bail;
       
   707 		PyList_SET_ITEM(rfdslist, i, obj);
       
   708 	}
       
   709 	return rfdslist;
       
   710 
       
   711 bail:
       
   712 	Py_XDECREF(rfdslist);
       
   713 	return NULL;
       
   714 }
       
   715 
   651 #endif /* ndef _WIN32 */
   716 #endif /* ndef _WIN32 */
   652 
   717 
   653 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
   718 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
   654 {
   719 {
   655 	PyObject *statobj = NULL; /* initialize - optional arg */
   720 	PyObject *statobj = NULL; /* initialize - optional arg */
   814 "On error, this function may raise either a WindowsError or an IOError."},
   879 "On error, this function may raise either a WindowsError or an IOError."},
   815 #else
   880 #else
   816 	{"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS,
   881 	{"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS,
   817 	 "stat a series of files or symlinks\n"
   882 	 "stat a series of files or symlinks\n"
   818 "Returns None for non-existent entries and entries of other types.\n"},
   883 "Returns None for non-existent entries and entries of other types.\n"},
       
   884 	{"recvfds", (PyCFunction)recvfds, METH_VARARGS,
       
   885 	 "receive list of file descriptors via socket\n"},
   819 #endif
   886 #endif
   820 #ifdef __APPLE__
   887 #ifdef __APPLE__
   821 	{
   888 	{
   822 		"isgui", (PyCFunction)isgui, METH_NOARGS,
   889 		"isgui", (PyCFunction)isgui, METH_NOARGS,
   823 		"Is a CoreGraphics session available?"
   890 		"Is a CoreGraphics session available?"