From: Serhiy Storchaka Date: Mon, 16 Feb 2015 11:33:32 +0000 (+0200) Subject: Issue #23446: Use PyMem_New instead of PyMem_Malloc to avoid possible integer X-Git-Tag: v3.5.0a2~135 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4d0d9829851915e97ae392dd803976be6c95c8d1;p=python Issue #23446: Use PyMem_New instead of PyMem_Malloc to avoid possible integer overflows. Added few missed PyErr_NoMemory(). --- 4d0d9829851915e97ae392dd803976be6c95c8d1 diff --cc Modules/posixmodule.c index 118a380e71,d45f59e5f1..c019b1609b --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@@ -4414,133 -4310,101 +4414,133 @@@ os_link_impl(PyModuleDef *module, path_ #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS - if (src.wide) - result = MoveFileExW(src.wide, dst.wide, flags); + if (src->wide) + result = CreateHardLinkW(dst->wide, src->wide, NULL); else - result = MoveFileExA(src.narrow, dst.narrow, flags); + result = CreateHardLinkA(dst->narrow, src->narrow, NULL); Py_END_ALLOW_THREADS - if (!result) { - return_value = path_error2(&src, &dst); - goto exit; - } - + if (!result) + return path_error2(src, dst); #else Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_RENAMEAT - if (dir_fd_specified) - result = renameat(src_dir_fd, src.narrow, dst_dir_fd, dst.narrow); +#ifdef HAVE_LINKAT + if ((src_dir_fd != DEFAULT_DIR_FD) || + (dst_dir_fd != DEFAULT_DIR_FD) || + (!follow_symlinks)) + result = linkat(src_dir_fd, src->narrow, + dst_dir_fd, dst->narrow, + follow_symlinks ? AT_SYMLINK_FOLLOW : 0); else #endif - result = rename(src.narrow, dst.narrow); + result = link(src->narrow, dst->narrow); Py_END_ALLOW_THREADS - if (result) { - return_value = path_error2(&src, &dst); - goto exit; - } + if (result) + return path_error2(src, dst); #endif - Py_INCREF(Py_None); - return_value = Py_None; -exit: - path_cleanup(&src); - path_cleanup(&dst); - return return_value; + Py_RETURN_NONE; } +#endif -PyDoc_STRVAR(posix_rename__doc__, -"rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\ -Rename a file or directory.\n\ -\n\ -If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\ - descriptor open to a directory, and the respective path string (src or dst)\n\ - should be relative; the path will then be relative to that directory.\n\ -src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\ - If they are unavailable, using them will raise a NotImplementedError."); +#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) static PyObject * -posix_rename(PyObject *self, PyObject *args, PyObject *kwargs) +_listdir_windows_no_opendir(path_t *path, PyObject *list) { - return internal_rename(args, kwargs, 0); -} - -PyDoc_STRVAR(posix_replace__doc__, -"replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\ -Rename a file or directory, overwriting the destination.\n\ -\n\ -If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\ - descriptor open to a directory, and the respective path string (src or dst)\n\ - should be relative; the path will then be relative to that directory.\n\ -src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\ - If they are unavailable, using them will raise a NotImplementedError."); + PyObject *v; + HANDLE hFindFile = INVALID_HANDLE_VALUE; + BOOL result; + WIN32_FIND_DATA FileData; + char namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ + char *bufptr = namebuf; + /* only claim to have space for MAX_PATH */ + Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; + PyObject *po = NULL; + wchar_t *wnamebuf = NULL; -static PyObject * -posix_replace(PyObject *self, PyObject *args, PyObject *kwargs) -{ - return internal_rename(args, kwargs, 1); -} + if (!path->narrow) { + WIN32_FIND_DATAW wFileData; + wchar_t *po_wchars; -PyDoc_STRVAR(posix_rmdir__doc__, -"rmdir(path, *, dir_fd=None)\n\n\ -Remove a directory.\n\ -\n\ -If dir_fd is not None, it should be a file descriptor open to a directory,\n\ - and path should be relative; path will then be relative to that directory.\n\ -dir_fd may not be implemented on your platform.\n\ - If it is unavailable, using it will raise a NotImplementedError."); + if (!path->wide) { /* Default arg: "." */ + po_wchars = L"."; + len = 1; + } else { + po_wchars = path->wide; + len = wcslen(path->wide); + } + /* The +5 is so we can append "\\*.*\0" */ - wnamebuf = PyMem_Malloc((len + 5) * sizeof(wchar_t)); ++ wnamebuf = PyMem_New(wchar_t, len + 5); + if (!wnamebuf) { + PyErr_NoMemory(); + goto exit; + } + wcscpy(wnamebuf, po_wchars); + if (len > 0) { + wchar_t wch = wnamebuf[len-1]; + if (wch != SEP && wch != ALTSEP && wch != L':') + wnamebuf[len++] = SEP; + wcscpy(wnamebuf + len, L"*.*"); + } + if ((list = PyList_New(0)) == NULL) { + goto exit; + } + Py_BEGIN_ALLOW_THREADS + hFindFile = FindFirstFileW(wnamebuf, &wFileData); + Py_END_ALLOW_THREADS + if (hFindFile == INVALID_HANDLE_VALUE) { + int error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) + goto exit; + Py_DECREF(list); + list = path_error(path); + goto exit; + } + do { + /* Skip over . and .. */ + if (wcscmp(wFileData.cFileName, L".") != 0 && + wcscmp(wFileData.cFileName, L"..") != 0) { + v = PyUnicode_FromWideChar(wFileData.cFileName, + wcslen(wFileData.cFileName)); + if (v == NULL) { + Py_DECREF(list); + list = NULL; + break; + } + if (PyList_Append(list, v) != 0) { + Py_DECREF(v); + Py_DECREF(list); + list = NULL; + break; + } + Py_DECREF(v); + } + Py_BEGIN_ALLOW_THREADS + result = FindNextFileW(hFindFile, &wFileData); + Py_END_ALLOW_THREADS + /* FindNextFile sets error to ERROR_NO_MORE_FILES if + it got to the end of the directory. */ + if (!result && GetLastError() != ERROR_NO_MORE_FILES) { + Py_DECREF(list); + list = path_error(path); + goto exit; + } + } while (result == TRUE); -static PyObject * -posix_rmdir(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - int dir_fd = DEFAULT_DIR_FD; - static char *keywords[] = {"path", "dir_fd", NULL}; - int result; - PyObject *return_value = NULL; + goto exit; + } + strcpy(namebuf, path->narrow); + len = path->length; + if (len > 0) { + char ch = namebuf[len-1]; + if (ch != '\\' && ch != '/' && ch != ':') + namebuf[len++] = '\\'; + strcpy(namebuf + len, "*.*"); + } - memset(&path, 0, sizeof(path)); - path.function_name = "rmdir"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:rmdir", keywords, - path_converter, &path, -#ifdef HAVE_UNLINKAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd -#endif - )) + if ((list = PyList_New(0)) == NULL) return NULL; Py_BEGIN_ALLOW_THREADS @@@ -4772,367 -4594,380 +4772,367 @@@ exit return return_value; } +static PyObject * +os_listdir_impl(PyModuleDef *module, path_t *path) +/*[clinic end generated code: output=e159bd9be6909018 input=09e300416e3cd729]*/ +{ +#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) + return _listdir_windows_no_opendir(path, NULL); +#else + return _posix_listdir(path, NULL); +#endif +} -PyDoc_STRVAR(posix_uname__doc__, -"uname() -> uname_result\n\n\ -Return an object identifying the current operating system.\n\ -The object behaves like a named tuple with the following fields:\n\ - (sysname, nodename, release, version, machine)"); - -static PyStructSequence_Field uname_result_fields[] = { - {"sysname", "operating system name"}, - {"nodename", "name of machine on network (implementation-defined)"}, - {"release", "operating system release"}, - {"version", "operating system version"}, - {"machine", "hardware identifier"}, - {NULL} -}; - -PyDoc_STRVAR(uname_result__doc__, -"uname_result: Result from os.uname().\n\n\ -This object may be accessed either as a tuple of\n\ - (sysname, nodename, release, version, machine),\n\ -or via the attributes sysname, nodename, release, version, and machine.\n\ -\n\ -See os.uname for more information."); - -static PyStructSequence_Desc uname_result_desc = { - "uname_result", /* name */ - uname_result__doc__, /* doc */ - uname_result_fields, - 5 -}; - -static PyTypeObject UnameResultType; - - -#ifdef HAVE_UNAME +#ifdef MS_WINDOWS +/* A helper function for abspath on win32 */ +/* AC 3.5: probably just convert to using path converter */ static PyObject * -posix_uname(PyObject *self, PyObject *noargs) +posix__getfullpathname(PyObject *self, PyObject *args) { - struct utsname u; - int res; - PyObject *value; + const char *path; + char outbuf[MAX_PATH]; + char *temp; + PyObject *po; - Py_BEGIN_ALLOW_THREADS - res = uname(&u); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); + if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) + { + wchar_t *wpath; + wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; + wchar_t *wtemp; + DWORD result; + PyObject *v; - value = PyStructSequence_New(&UnameResultType); - if (value == NULL) + wpath = PyUnicode_AsUnicode(po); + if (wpath == NULL) + return NULL; + result = GetFullPathNameW(wpath, + Py_ARRAY_LENGTH(woutbuf), + woutbuf, &wtemp); + if (result > Py_ARRAY_LENGTH(woutbuf)) { - woutbufp = PyMem_Malloc(result * sizeof(wchar_t)); ++ woutbufp = PyMem_New(wchar_t, result); + if (!woutbufp) + return PyErr_NoMemory(); + result = GetFullPathNameW(wpath, result, woutbufp, &wtemp); + } + if (result) + v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp)); + else + v = win32_error_object("GetFullPathNameW", po); + if (woutbufp != woutbuf) + PyMem_Free(woutbufp); + return v; + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + + if (!PyArg_ParseTuple (args, "y:_getfullpathname", + &path)) + return NULL; + if (win32_warn_bytes_api()) + return NULL; + if (!GetFullPathName(path, Py_ARRAY_LENGTH(outbuf), + outbuf, &temp)) { + win32_error("GetFullPathName", path); return NULL; + } + if (PyUnicode_Check(PyTuple_GetItem(args, 0))) { + return PyUnicode_Decode(outbuf, strlen(outbuf), + Py_FileSystemDefaultEncoding, NULL); + } + return PyBytes_FromString(outbuf); +} -#define SET(i, field) \ - { \ - PyObject *o = PyUnicode_DecodeFSDefault(field); \ - if (!o) { \ - Py_DECREF(value); \ - return NULL; \ - } \ - PyStructSequence_SET_ITEM(value, i, o); \ - } \ - SET(0, u.sysname); - SET(1, u.nodename); - SET(2, u.release); - SET(3, u.version); - SET(4, u.machine); +/*[clinic input] +os._getfinalpathname -#undef SET + path: unicode + / - return value; -} -#endif /* HAVE_UNAME */ +A helper function for samepath on windows. +[clinic start generated code]*/ +PyDoc_STRVAR(os__getfinalpathname__doc__, +"_getfinalpathname($module, path, /)\n" +"--\n" +"\n" +"A helper function for samepath on windows."); -PyDoc_STRVAR(posix_utime__doc__, -"utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)\n\ -Set the access and modified time of path.\n\ -\n\ -path may always be specified as a string.\n\ -On some platforms, path may also be specified as an open file descriptor.\n\ - If this functionality is unavailable, using it raises an exception.\n\ -\n\ -If times is not None, it must be a tuple (atime, mtime);\n\ - atime and mtime should be expressed as float seconds since the epoch.\n\ -If ns is not None, it must be a tuple (atime_ns, mtime_ns);\n\ - atime_ns and mtime_ns should be expressed as integer nanoseconds\n\ - since the epoch.\n\ -If both times and ns are None, utime uses the current time.\n\ -Specifying tuples for both times and ns is an error.\n\ -\n\ -If dir_fd is not None, it should be a file descriptor open to a directory,\n\ - and path should be relative; path will then be relative to that directory.\n\ -If follow_symlinks is False, and the last element of the path is a symbolic\n\ - link, utime will modify the symbolic link itself instead of the file the\n\ - link points to.\n\ -It is an error to use dir_fd or follow_symlinks when specifying path\n\ - as an open file descriptor.\n\ -dir_fd and follow_symlinks may not be available on your platform.\n\ - If they are unavailable, using them will raise a NotImplementedError."); +#define OS__GETFINALPATHNAME_METHODDEF \ + {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_VARARGS, os__getfinalpathname__doc__}, -typedef struct { - int now; - time_t atime_s; - long atime_ns; - time_t mtime_s; - long mtime_ns; -} utime_t; +static PyObject * +os__getfinalpathname_impl(PyModuleDef *module, PyObject *path); -/* - * these macros assume that "ut" is a pointer to a utime_t - * they also intentionally leak the declaration of a pointer named "time" - */ -#define UTIME_TO_TIMESPEC \ - struct timespec ts[2]; \ - struct timespec *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - ts[0].tv_sec = ut->atime_s; \ - ts[0].tv_nsec = ut->atime_ns; \ - ts[1].tv_sec = ut->mtime_s; \ - ts[1].tv_nsec = ut->mtime_ns; \ - time = ts; \ - } \ +static PyObject * +os__getfinalpathname(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *path; -#define UTIME_TO_TIMEVAL \ - struct timeval tv[2]; \ - struct timeval *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - tv[0].tv_sec = ut->atime_s; \ - tv[0].tv_usec = ut->atime_ns / 1000; \ - tv[1].tv_sec = ut->mtime_s; \ - tv[1].tv_usec = ut->mtime_ns / 1000; \ - time = tv; \ - } \ + if (!PyArg_ParseTuple(args, + "U:_getfinalpathname", + &path)) + goto exit; + return_value = os__getfinalpathname_impl(module, path); -#define UTIME_TO_UTIMBUF \ - struct utimbuf u; \ - struct utimbuf *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - u.actime = ut->atime_s; \ - u.modtime = ut->mtime_s; \ - time = &u; \ - } +exit: + return return_value; +} -#define UTIME_TO_TIME_T \ - time_t timet[2]; \ - time_t *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - timet[0] = ut->atime_s; \ - timet[1] = ut->mtime_s; \ - time = timet; \ - } \ +static PyObject * +os__getfinalpathname_impl(PyModuleDef *module, PyObject *path) +/*[clinic end generated code: output=4563c6eacf1b0881 input=71d5e89334891bf4]*/ +{ + HANDLE hFile; + int buf_size; + wchar_t *target_path; + int result_length; + PyObject *result; + wchar_t *path_wchar; + path_wchar = PyUnicode_AsUnicode(path); + if (path_wchar == NULL) + return NULL; -#define UTIME_HAVE_DIR_FD (defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)) + if(!check_GetFinalPathNameByHandle()) { + /* If the OS doesn't have GetFinalPathNameByHandle, return a + NotImplementedError. */ + return PyErr_Format(PyExc_NotImplementedError, + "GetFinalPathNameByHandle not available on this platform"); + } -#if UTIME_HAVE_DIR_FD + hFile = CreateFileW( + path_wchar, + 0, /* desired access */ + 0, /* share mode */ + NULL, /* security attributes */ + OPEN_EXISTING, + /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ + FILE_FLAG_BACKUP_SEMANTICS, + NULL); -static int -utime_dir_fd(utime_t *ut, int dir_fd, char *path, int follow_symlinks) -{ -#ifdef HAVE_UTIMENSAT - int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; - UTIME_TO_TIMESPEC; - return utimensat(dir_fd, path, time, flags); -#elif defined(HAVE_FUTIMESAT) - UTIME_TO_TIMEVAL; - /* - * follow_symlinks will never be false here; - * we only allow !follow_symlinks and dir_fd together - * if we have utimensat() - */ - assert(follow_symlinks); - return futimesat(dir_fd, path, time); -#endif -} + if(hFile == INVALID_HANDLE_VALUE) + return win32_error_object("CreateFileW", path); -#endif + /* We have a good handle to the target, use it to determine the + target path name. */ + buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT); -#define UTIME_HAVE_FD (defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)) + if(!buf_size) + return win32_error_object("GetFinalPathNameByHandle", path); - target_path = (wchar_t *)PyMem_Malloc((buf_size+1)*sizeof(wchar_t)); -#if UTIME_HAVE_FD ++ target_path = PyMem_New(wchar_t, buf_size+1); + if(!target_path) + return PyErr_NoMemory(); -static int -utime_fd(utime_t *ut, int fd) -{ -#ifdef HAVE_FUTIMENS - UTIME_TO_TIMESPEC; - return futimens(fd, time); -#else - UTIME_TO_TIMEVAL; - return futimes(fd, time); -#endif + result_length = Py_GetFinalPathNameByHandleW(hFile, target_path, + buf_size, VOLUME_NAME_DOS); + if(!result_length) + return win32_error_object("GetFinalPathNamyByHandle", path); + + if(!CloseHandle(hFile)) + return win32_error_object("CloseHandle", path); + + target_path[result_length] = 0; + result = PyUnicode_FromWideChar(target_path, result_length); + PyMem_Free(target_path); + return result; } -#endif +PyDoc_STRVAR(posix__isdir__doc__, +"Return true if the pathname refers to an existing directory."); +/* AC 3.5: convert using path converter */ +static PyObject * +posix__isdir(PyObject *self, PyObject *args) +{ + const char *path; + PyObject *po; + DWORD attributes; -#define UTIME_HAVE_NOFOLLOW_SYMLINKS \ - (defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)) + if (PyArg_ParseTuple(args, "U|:_isdir", &po)) { + wchar_t *wpath = PyUnicode_AsUnicode(po); + if (wpath == NULL) + return NULL; -#if UTIME_HAVE_NOFOLLOW_SYMLINKS + attributes = GetFileAttributesW(wpath); + if (attributes == INVALID_FILE_ATTRIBUTES) + Py_RETURN_FALSE; + goto check; + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); -static int -utime_nofollow_symlinks(utime_t *ut, char *path) -{ -#ifdef HAVE_UTIMENSAT - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); -#else - UTIME_TO_TIMEVAL; - return lutimes(path, time); -#endif + if (!PyArg_ParseTuple(args, "y:_isdir", &path)) + return NULL; + if (win32_warn_bytes_api()) + return NULL; + attributes = GetFileAttributesA(path); + if (attributes == INVALID_FILE_ATTRIBUTES) + Py_RETURN_FALSE; + +check: + if (attributes & FILE_ATTRIBUTE_DIRECTORY) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; } -#endif -#ifndef MS_WINDOWS +/*[clinic input] +os._getvolumepathname -static int -utime_default(utime_t *ut, char *path) -{ -#ifdef HAVE_UTIMENSAT - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, 0); -#elif defined(HAVE_UTIMES) - UTIME_TO_TIMEVAL; - return utimes(path, time); -#elif defined(HAVE_UTIME_H) - UTIME_TO_UTIMBUF; - return utime(path, time); -#else - UTIME_TO_TIME_T; - return utime(path, time); -#endif -} + path: unicode -#endif +A helper function for ismount on Win32. +[clinic start generated code]*/ -static int -split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns) +PyDoc_STRVAR(os__getvolumepathname__doc__, +"_getvolumepathname($module, /, path)\n" +"--\n" +"\n" +"A helper function for ismount on Win32."); + +#define OS__GETVOLUMEPATHNAME_METHODDEF \ + {"_getvolumepathname", (PyCFunction)os__getvolumepathname, METH_VARARGS|METH_KEYWORDS, os__getvolumepathname__doc__}, + +static PyObject * +os__getvolumepathname_impl(PyModuleDef *module, PyObject *path); + +static PyObject * +os__getvolumepathname(PyModuleDef *module, PyObject *args, PyObject *kwargs) { - int result = 0; - PyObject *divmod; - divmod = PyNumber_Divmod(py_long, billion); - if (!divmod) - goto exit; - *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0)); - if ((*s == -1) && PyErr_Occurred()) - goto exit; - *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1)); - if ((*ns == -1) && PyErr_Occurred()) + PyObject *return_value = NULL; + static char *_keywords[] = {"path", NULL}; + PyObject *path; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "U:_getvolumepathname", _keywords, + &path)) goto exit; + return_value = os__getvolumepathname_impl(module, path); - result = 1; exit: - Py_XDECREF(divmod); - return result; + return return_value; } static PyObject * -posix_utime(PyObject *self, PyObject *args, PyObject *kwargs) +os__getvolumepathname_impl(PyModuleDef *module, PyObject *path) +/*[clinic end generated code: output=ac0833b6d6da7657 input=7eacadc40acbda6b]*/ { - path_t path; - PyObject *times = NULL; - PyObject *ns = NULL; - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - char *keywords[] = {"path", "times", "ns", "dir_fd", - "follow_symlinks", NULL}; - - utime_t utime; + PyObject *result; + wchar_t *path_wchar, *mountpath=NULL; + size_t buflen; + BOOL ret; -#ifdef MS_WINDOWS - HANDLE hFile; - FILETIME atime, mtime; -#else - int result; -#endif + path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen); + if (path_wchar == NULL) + return NULL; + buflen += 1; - PyObject *return_value = NULL; + /* Volume path should be shorter than entire path */ + buflen = Py_MAX(buflen, MAX_PATH); - memset(&path, 0, sizeof(path)); - path.function_name = "utime"; - memset(&utime, 0, sizeof(utime_t)); -#if UTIME_HAVE_FD - path.allow_fd = 1; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|O$OO&p:utime", keywords, - path_converter, &path, - ×, &ns, -#if UTIME_HAVE_DIR_FD - dir_fd_converter, &dir_fd, -#else - dir_fd_unavailable, &dir_fd, -#endif - &follow_symlinks - )) + if (buflen > DWORD_MAX) { + PyErr_SetString(PyExc_OverflowError, "path too long"); return NULL; + } - mountpath = (wchar_t *)PyMem_Malloc(buflen * sizeof(wchar_t)); - if (times && (times != Py_None) && ns) { - PyErr_SetString(PyExc_ValueError, - "utime: you may specify either 'times'" - " or 'ns' but not both"); ++ mountpath = PyMem_New(wchar_t, buflen); + if (mountpath == NULL) + return PyErr_NoMemory(); + + Py_BEGIN_ALLOW_THREADS + ret = GetVolumePathNameW(path_wchar, mountpath, + Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); + Py_END_ALLOW_THREADS + + if (!ret) { + result = win32_error_object("_getvolumepathname", path); goto exit; } + result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); - if (times && (times != Py_None)) { - time_t a_sec, m_sec; - long a_nsec, m_nsec; - if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) { - PyErr_SetString(PyExc_TypeError, - "utime: 'times' must be either" - " a tuple of two ints or None"); - goto exit; - } - utime.now = 0; - if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), - &a_sec, &a_nsec, _PyTime_ROUND_DOWN) == -1 || - _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), - &m_sec, &m_nsec, _PyTime_ROUND_DOWN) == -1) { - goto exit; - } - utime.atime_s = a_sec; - utime.atime_ns = a_nsec; - utime.mtime_s = m_sec; - utime.mtime_ns = m_nsec; - } - else if (ns) { - if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) { - PyErr_SetString(PyExc_TypeError, - "utime: 'ns' must be a tuple of two ints"); - goto exit; - } - utime.now = 0; - if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0), - &utime.atime_s, &utime.atime_ns) || - !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1), - &utime.mtime_s, &utime.mtime_ns)) { - goto exit; - } - } - else { - /* times and ns are both None/unspecified. use "now". */ - utime.now = 1; - } +exit: + PyMem_Free(mountpath); + return result; +} -#if !UTIME_HAVE_NOFOLLOW_SYMLINKS - if (follow_symlinks_specified("utime", follow_symlinks)) - goto exit; -#endif +#endif /* MS_WINDOWS */ - if (path_and_dir_fd_invalid("utime", &path, dir_fd) || - dir_fd_and_fd_invalid("utime", dir_fd, path.fd) || - fd_and_follow_symlinks_invalid("utime", path.fd, follow_symlinks)) - goto exit; -#if !defined(HAVE_UTIMENSAT) - if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { - PyErr_SetString(PyExc_ValueError, - "utime: cannot use dir_fd and follow_symlinks " - "together on this platform"); +/*[clinic input] +os.mkdir + + path : path_t + + mode: int = 0o777 + + * + + dir_fd : dir_fd(requires='mkdirat') = None + +# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\ + +Create a directory. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. + +The mode argument is ignored on Windows. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_mkdir__doc__, +"mkdir($module, /, path, mode=511, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a directory.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError.\n" +"\n" +"The mode argument is ignored on Windows."); + +#define OS_MKDIR_METHODDEF \ + {"mkdir", (PyCFunction)os_mkdir, METH_VARARGS|METH_KEYWORDS, os_mkdir__doc__}, + +static PyObject * +os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd); + +static PyObject * +os_mkdir(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "mode", "dir_fd", NULL}; + path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0); + int mode = 511; + int dir_fd = DEFAULT_DIR_FD; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&|i$O&:mkdir", _keywords, + path_converter, &path, &mode, MKDIRAT_DIR_FD_CONVERTER, &dir_fd)) goto exit; - } -#endif + return_value = os_mkdir_impl(module, &path, mode, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +static PyObject * +os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd) +/*[clinic end generated code: output=55c6ef2bc1b207e6 input=e965f68377e9b1ce]*/ +{ + int result; #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS @@@ -7617,7135 -7844,2152 +7617,7135 @@@ os_sched_getparam_impl(PyModuleDef *mod } -PyDoc_STRVAR(posix_dup2__doc__, -"dup2(old_fd, new_fd)\n\n\ -Duplicate file descriptor."); +/*[clinic input] +os.sched_setparam + pid: pid_t + param: sched_param + / -static PyObject * -posix_dup2(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *keywords[] = {"fd", "fd2", "inheritable", NULL}; - int fd, fd2; - int inheritable = 1; - int res; -#if defined(HAVE_DUP3) && \ - !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) - /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ - int dup3_works = -1; -#endif - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i:dup2", keywords, - &fd, &fd2, &inheritable)) - return NULL; - - if (!_PyVerify_fd_dup2(fd, fd2)) - return posix_error(); - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - res = dup2(fd, fd2); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - - /* Character files like console cannot be make non-inheritable */ - if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { - close(fd2); - return NULL; - } +Set scheduling parameters for the process identified by pid. -#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC) - Py_BEGIN_ALLOW_THREADS - if (!inheritable) - res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2); - else - res = dup2(fd, fd2); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); +If pid is 0, sets parameters for the calling process. +param should be an instance of sched_param. +[clinic start generated code]*/ -#else +PyDoc_STRVAR(os_sched_setparam__doc__, +"sched_setparam($module, pid, param, /)\n" +"--\n" +"\n" +"Set scheduling parameters for the process identified by pid.\n" +"\n" +"If pid is 0, sets parameters for the calling process.\n" +"param should be an instance of sched_param."); -#ifdef HAVE_DUP3 - if (!inheritable && dup3_works != 0) { - Py_BEGIN_ALLOW_THREADS - res = dup3(fd, fd2, O_CLOEXEC); - Py_END_ALLOW_THREADS - if (res < 0) { - if (dup3_works == -1) - dup3_works = (errno != ENOSYS); - if (dup3_works) - return posix_error(); - } - } +#define OS_SCHED_SETPARAM_METHODDEF \ + {"sched_setparam", (PyCFunction)os_sched_setparam, METH_VARARGS, os_sched_setparam__doc__}, - if (inheritable || dup3_works == 0) - { -#endif - Py_BEGIN_ALLOW_THREADS - res = dup2(fd, fd2); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); +static PyObject * +os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param); - if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { - close(fd2); - return NULL; - } -#ifdef HAVE_DUP3 - } -#endif +static PyObject * +os_sched_setparam(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + pid_t pid; + struct sched_param param; -#endif + if (!PyArg_ParseTuple(args, + "" _Py_PARSE_PID "O&:sched_setparam", + &pid, convert_sched_param, ¶m)) + goto exit; + return_value = os_sched_setparam_impl(module, pid, ¶m); - Py_INCREF(Py_None); - return Py_None; +exit: + return return_value; } -#ifdef HAVE_LOCKF -PyDoc_STRVAR(posix_lockf__doc__, -"lockf(fd, cmd, len)\n\n\ -Apply, test or remove a POSIX lock on an open file descriptor.\n\n\ -fd is an open file descriptor.\n\ -cmd specifies the command to use - one of F_LOCK, F_TLOCK, F_ULOCK or\n\ -F_TEST.\n\ -len specifies the section of the file to lock."); - static PyObject * -posix_lockf(PyObject *self, PyObject *args) +os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param) +/*[clinic end generated code: output=488bdf5bcbe0d4e8 input=6b8d6dfcecdc21bd]*/ { - int fd, cmd, res; - off_t len; - if (!PyArg_ParseTuple(args, "iiO&:lockf", - &fd, &cmd, _parse_off_t, &len)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - res = lockf(fd, cmd, len); - Py_END_ALLOW_THREADS - - if (res < 0) + if (sched_setparam(pid, param)) return posix_error(); - Py_RETURN_NONE; } -#endif - +#endif /* HAVE_SCHED_SETPARAM */ -PyDoc_STRVAR(posix_lseek__doc__, -"lseek(fd, pos, how) -> newpos\n\n\ -Set the current position of a file descriptor.\n\ -Return the new cursor position in bytes, starting from the beginning."); -static PyObject * -posix_lseek(PyObject *self, PyObject *args) -{ - int fd, how; -#ifdef MS_WINDOWS - PY_LONG_LONG pos, res; -#else - off_t pos, res; -#endif - PyObject *posobj; - if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how)) - return NULL; -#ifdef SEEK_SET - /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ - switch (how) { - case 0: how = SEEK_SET; break; - case 1: how = SEEK_CUR; break; - case 2: how = SEEK_END; break; - } -#endif /* SEEK_END */ +#ifdef HAVE_SCHED_RR_GET_INTERVAL +/*[clinic input] +os.sched_rr_get_interval -> double + pid: pid_t + / -#if !defined(HAVE_LARGEFILE_SUPPORT) - pos = PyLong_AsLong(posobj); -#else - pos = PyLong_AsLongLong(posobj); -#endif - if (PyErr_Occurred()) - return NULL; +Return the round-robin quantum for the process identified by pid, in seconds. - if (!_PyVerify_fd(fd)) - return posix_error(); - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - res = _lseeki64(fd, pos, how); -#else - res = lseek(fd, pos, how); -#endif - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); +Value returned is a float. +[clinic start generated code]*/ -#if !defined(HAVE_LARGEFILE_SUPPORT) - return PyLong_FromLong(res); -#else - return PyLong_FromLongLong(res); -#endif -} +PyDoc_STRVAR(os_sched_rr_get_interval__doc__, +"sched_rr_get_interval($module, pid, /)\n" +"--\n" +"\n" +"Return the round-robin quantum for the process identified by pid, in seconds.\n" +"\n" +"Value returned is a float."); +#define OS_SCHED_RR_GET_INTERVAL_METHODDEF \ + {"sched_rr_get_interval", (PyCFunction)os_sched_rr_get_interval, METH_VARARGS, os_sched_rr_get_interval__doc__}, -PyDoc_STRVAR(posix_read__doc__, -"read(fd, buffersize) -> bytes\n\n\ -Read a file descriptor."); +static double +os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid); static PyObject * -posix_read(PyObject *self, PyObject *args) +os_sched_rr_get_interval(PyModuleDef *module, PyObject *args) { - int fd, size; - Py_ssize_t n; - PyObject *buffer; - if (!PyArg_ParseTuple(args, "ii:read", &fd, &size)) - return NULL; - if (size < 0) { - errno = EINVAL; - return posix_error(); - } - buffer = PyBytes_FromStringAndSize((char *)NULL, size); - if (buffer == NULL) - return NULL; - if (!_PyVerify_fd(fd)) { - Py_DECREF(buffer); - return posix_error(); - } - Py_BEGIN_ALLOW_THREADS - n = read(fd, PyBytes_AS_STRING(buffer), size); - Py_END_ALLOW_THREADS - if (n < 0) { - Py_DECREF(buffer); - return posix_error(); - } - if (n != size) - _PyBytes_Resize(&buffer, n); - return buffer; + PyObject *return_value = NULL; + pid_t pid; + double _return_value; + + if (!PyArg_ParseTuple(args, + "" _Py_PARSE_PID ":sched_rr_get_interval", + &pid)) + goto exit; + _return_value = os_sched_rr_get_interval_impl(module, pid); + if ((_return_value == -1.0) && PyErr_Occurred()) + goto exit; + return_value = PyFloat_FromDouble(_return_value); + +exit: + return return_value; } -#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ - || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV) -static Py_ssize_t -iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type) +static double +os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid) +/*[clinic end generated code: output=5b3b8d1f27fb2c0a input=2a973da15cca6fae]*/ { - int i, j; - Py_ssize_t blen, total = 0; - - *iov = PyMem_New(struct iovec, cnt); - if (*iov == NULL) { - PyErr_NoMemory(); - return -1; + struct timespec interval; + if (sched_rr_get_interval(pid, &interval)) { + posix_error(); + return -1.0; } + return (double)interval.tv_sec + 1e-9*interval.tv_nsec; +} +#endif /* HAVE_SCHED_RR_GET_INTERVAL */ - *buf = PyMem_New(Py_buffer, cnt); - if (*buf == NULL) { - PyMem_Del(*iov); - PyErr_NoMemory(); - return -1; - } - for (i = 0; i < cnt; i++) { - PyObject *item = PySequence_GetItem(seq, i); - if (item == NULL) - goto fail; - if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { - Py_DECREF(item); - goto fail; - } - Py_DECREF(item); - (*iov)[i].iov_base = (*buf)[i].buf; - blen = (*buf)[i].len; - (*iov)[i].iov_len = blen; - total += blen; - } - return total; +/*[clinic input] +os.sched_yield -fail: - PyMem_Del(*iov); - for (j = 0; j < i; j++) { - PyBuffer_Release(&(*buf)[j]); - } - PyMem_Del(*buf); - return -1; -} +Voluntarily relinquish the CPU. +[clinic start generated code]*/ -static void -iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) +PyDoc_STRVAR(os_sched_yield__doc__, +"sched_yield($module, /)\n" +"--\n" +"\n" +"Voluntarily relinquish the CPU."); + +#define OS_SCHED_YIELD_METHODDEF \ + {"sched_yield", (PyCFunction)os_sched_yield, METH_NOARGS, os_sched_yield__doc__}, + +static PyObject * +os_sched_yield_impl(PyModuleDef *module); + +static PyObject * +os_sched_yield(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) { - int i; - PyMem_Del(iov); - for (i = 0; i < cnt; i++) { - PyBuffer_Release(&buf[i]); - } - PyMem_Del(buf); + return os_sched_yield_impl(module); } -#endif - -#ifdef HAVE_READV -PyDoc_STRVAR(posix_readv__doc__, -"readv(fd, buffers) -> bytesread\n\n\ -Read from a file descriptor fd into a number of mutable, bytes-like\n\ -objects (\"buffers\"). readv will transfer data into each buffer\n\ -until it is full and then move on to the next buffer in the sequence\n\ -to hold the rest of the data.\n\n\ -readv returns the total number of bytes read (which may be less than\n\ -the total capacity of all the buffers."); static PyObject * -posix_readv(PyObject *self, PyObject *args) +os_sched_yield_impl(PyModuleDef *module) +/*[clinic end generated code: output=9d2e5f29f1370324 input=e54d6f98189391d4]*/ { - int fd, cnt; - Py_ssize_t n; - PyObject *seq; - struct iovec *iov; - Py_buffer *buf; + if (sched_yield()) + return posix_error(); + Py_RETURN_NONE; +} - if (!PyArg_ParseTuple(args, "iO:readv", &fd, &seq)) - return NULL; - if (!PySequence_Check(seq)) { - PyErr_SetString(PyExc_TypeError, - "readv() arg 2 must be a sequence"); - return NULL; - } - cnt = PySequence_Size(seq); +#ifdef HAVE_SCHED_SETAFFINITY +/* The minimum number of CPUs allocated in a cpu_set_t */ +static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; - if (iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE) < 0) - return NULL; +/*[clinic input] +os.sched_setaffinity + pid: pid_t + mask : object + / - Py_BEGIN_ALLOW_THREADS - n = readv(fd, iov, cnt); - Py_END_ALLOW_THREADS +Set the CPU affinity of the process identified by pid to mask. - iov_cleanup(iov, buf, cnt); - if (n < 0) - return posix_error(); +mask should be an iterable of integers identifying CPUs. +[clinic start generated code]*/ - return PyLong_FromSsize_t(n); -} -#endif +PyDoc_STRVAR(os_sched_setaffinity__doc__, +"sched_setaffinity($module, pid, mask, /)\n" +"--\n" +"\n" +"Set the CPU affinity of the process identified by pid to mask.\n" +"\n" +"mask should be an iterable of integers identifying CPUs."); -#ifdef HAVE_PREAD -PyDoc_STRVAR(posix_pread__doc__, -"pread(fd, buffersize, offset) -> string\n\n\ -Read from a file descriptor, fd, at a position of offset. It will read up\n\ -to buffersize number of bytes. The file offset remains unchanged."); +#define OS_SCHED_SETAFFINITY_METHODDEF \ + {"sched_setaffinity", (PyCFunction)os_sched_setaffinity, METH_VARARGS, os_sched_setaffinity__doc__}, static PyObject * -posix_pread(PyObject *self, PyObject *args) -{ - int fd, size; - off_t offset; - Py_ssize_t n; - PyObject *buffer; - if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &size, _parse_off_t, &offset)) - return NULL; - - if (size < 0) { - errno = EINVAL; - return posix_error(); - } - buffer = PyBytes_FromStringAndSize((char *)NULL, size); - if (buffer == NULL) - return NULL; - if (!_PyVerify_fd(fd)) { - Py_DECREF(buffer); - return posix_error(); - } - Py_BEGIN_ALLOW_THREADS - n = pread(fd, PyBytes_AS_STRING(buffer), size, offset); - Py_END_ALLOW_THREADS - if (n < 0) { - Py_DECREF(buffer); - return posix_error(); - } - if (n != size) - _PyBytes_Resize(&buffer, n); - return buffer; -} -#endif - -PyDoc_STRVAR(posix_write__doc__, -"write(fd, data) -> byteswritten\n\n\ -Write bytes to a file descriptor."); +os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask); static PyObject * -posix_write(PyObject *self, PyObject *args) +os_sched_setaffinity(PyModuleDef *module, PyObject *args) { - Py_buffer pbuf; - int fd; - Py_ssize_t size, len; + PyObject *return_value = NULL; + pid_t pid; + PyObject *mask; - if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf)) - return NULL; - if (!_PyVerify_fd(fd)) { - PyBuffer_Release(&pbuf); - return posix_error(); - } - len = pbuf.len; - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (len > INT_MAX) - len = INT_MAX; - size = write(fd, pbuf.buf, (int)len); -#else - size = write(fd, pbuf.buf, len); -#endif - Py_END_ALLOW_THREADS - PyBuffer_Release(&pbuf); - if (size < 0) - return posix_error(); - return PyLong_FromSsize_t(size); -} + if (!PyArg_ParseTuple(args, + "" _Py_PARSE_PID "O:sched_setaffinity", + &pid, &mask)) + goto exit; + return_value = os_sched_setaffinity_impl(module, pid, mask); -#ifdef HAVE_SENDFILE -PyDoc_STRVAR(posix_sendfile__doc__, -"sendfile(out, in, offset, nbytes) -> byteswritten\n\ -sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\ - -> byteswritten\n\ -Copy nbytes bytes from file descriptor in to file descriptor out."); +exit: + return return_value; +} static PyObject * -posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict) +os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask) +/*[clinic end generated code: output=5199929738130196 input=a0791a597c7085ba]*/ { - int in, out; - Py_ssize_t ret; - off_t offset; + int ncpus; + size_t setsize; + cpu_set_t *cpu_set = NULL; + PyObject *iterator = NULL, *item; -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) -#ifndef __APPLE__ - Py_ssize_t len; -#endif - PyObject *headers = NULL, *trailers = NULL; - Py_buffer *hbuf, *tbuf; - off_t sbytes; - struct sf_hdtr sf; - int flags = 0; - static char *keywords[] = {"out", "in", - "offset", "count", - "headers", "trailers", "flags", NULL}; + iterator = PyObject_GetIter(mask); + if (iterator == NULL) + return NULL; - sf.headers = NULL; - sf.trailers = NULL; + ncpus = NCPUS_START; + setsize = CPU_ALLOC_SIZE(ncpus); + cpu_set = CPU_ALLOC(ncpus); + if (cpu_set == NULL) { + PyErr_NoMemory(); + goto error; + } + CPU_ZERO_S(setsize, cpu_set); -#ifdef __APPLE__ - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile", - keywords, &out, &in, _parse_off_t, &offset, _parse_off_t, &sbytes, -#else - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile", - keywords, &out, &in, _parse_off_t, &offset, &len, -#endif - &headers, &trailers, &flags)) - return NULL; - if (headers != NULL) { - if (!PySequence_Check(headers)) { - PyErr_SetString(PyExc_TypeError, - "sendfile() headers must be a sequence or None"); - return NULL; - } else { - Py_ssize_t i = 0; /* Avoid uninitialized warning */ - sf.hdr_cnt = PySequence_Size(headers); - if (sf.hdr_cnt > 0 && - (i = iov_setup(&(sf.headers), &hbuf, - headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0) - return NULL; -#ifdef __APPLE__ - sbytes += i; -#endif + while ((item = PyIter_Next(iterator))) { + long cpu; + if (!PyLong_Check(item)) { + PyErr_Format(PyExc_TypeError, + "expected an iterator of ints, " + "but iterator yielded %R", + Py_TYPE(item)); + Py_DECREF(item); + goto error; } - } - if (trailers != NULL) { - if (!PySequence_Check(trailers)) { - PyErr_SetString(PyExc_TypeError, - "sendfile() trailers must be a sequence or None"); - return NULL; - } else { - Py_ssize_t i = 0; /* Avoid uninitialized warning */ - sf.trl_cnt = PySequence_Size(trailers); - if (sf.trl_cnt > 0 && - (i = iov_setup(&(sf.trailers), &tbuf, - trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0) - return NULL; -#ifdef __APPLE__ - sbytes += i; -#endif + cpu = PyLong_AsLong(item); + Py_DECREF(item); + if (cpu < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_ValueError, "negative CPU number"); + goto error; } - } - - Py_BEGIN_ALLOW_THREADS -#ifdef __APPLE__ - ret = sendfile(in, out, offset, &sbytes, &sf, flags); -#else - ret = sendfile(in, out, offset, len, &sf, &sbytes, flags); -#endif - Py_END_ALLOW_THREADS - - if (sf.headers != NULL) - iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); - if (sf.trailers != NULL) - iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); - - if (ret < 0) { - if ((errno == EAGAIN) || (errno == EBUSY)) { - if (sbytes != 0) { - // some data has been sent - goto done; + if (cpu > INT_MAX - 1) { + PyErr_SetString(PyExc_OverflowError, "CPU number too large"); + goto error; + } + if (cpu >= ncpus) { + /* Grow CPU mask to fit the CPU number */ + int newncpus = ncpus; + cpu_set_t *newmask; + size_t newsetsize; + while (newncpus <= cpu) { + if (newncpus > INT_MAX / 2) + newncpus = cpu + 1; + else + newncpus = newncpus * 2; } - else { - // no data has been sent; upper application is supposed - // to retry on EAGAIN or EBUSY - return posix_error(); + newmask = CPU_ALLOC(newncpus); + if (newmask == NULL) { + PyErr_NoMemory(); + goto error; } + newsetsize = CPU_ALLOC_SIZE(newncpus); + CPU_ZERO_S(newsetsize, newmask); + memcpy(newmask, cpu_set, setsize); + CPU_FREE(cpu_set); + setsize = newsetsize; + cpu_set = newmask; + ncpus = newncpus; } - return posix_error(); + CPU_SET_S(cpu, setsize, cpu_set); } - goto done; - -done: - #if !defined(HAVE_LARGEFILE_SUPPORT) - return Py_BuildValue("l", sbytes); - #else - return Py_BuildValue("L", sbytes); - #endif + Py_CLEAR(iterator); -#else - Py_ssize_t count; - PyObject *offobj; - static char *keywords[] = {"out", "in", - "offset", "count", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile", - keywords, &out, &in, &offobj, &count)) - return NULL; -#ifdef linux - if (offobj == Py_None) { - Py_BEGIN_ALLOW_THREADS - ret = sendfile(out, in, NULL, count); - Py_END_ALLOW_THREADS - if (ret < 0) - return posix_error(); - return Py_BuildValue("n", ret); + if (sched_setaffinity(pid, setsize, cpu_set)) { + posix_error(); + goto error; } -#endif - if (!_parse_off_t(offobj, &offset)) - return NULL; - Py_BEGIN_ALLOW_THREADS - ret = sendfile(out, in, &offset, count); - Py_END_ALLOW_THREADS - if (ret < 0) - return posix_error(); - return Py_BuildValue("n", ret); -#endif + CPU_FREE(cpu_set); + Py_RETURN_NONE; + +error: + if (cpu_set) + CPU_FREE(cpu_set); + Py_XDECREF(iterator); + return NULL; } -#endif -PyDoc_STRVAR(posix_fstat__doc__, -"fstat(fd) -> stat result\n\n\ -Like stat(), but for an open file descriptor.\n\ -Equivalent to stat(fd=fd)."); -static PyObject * -posix_fstat(PyObject *self, 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) { -#ifdef MS_WINDOWS - return PyErr_SetFromWindowsErr(0); -#else - return posix_error(); -#endif - } +/*[clinic input] +os.sched_getaffinity + pid: pid_t + / - return _pystat_fromstructstat(&st); -} +Return the affinity of the process identified by pid. + +The affinity is returned as a set of CPU identifiers. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_sched_getaffinity__doc__, +"sched_getaffinity($module, pid, /)\n" +"--\n" +"\n" +"Return the affinity of the process identified by pid.\n" +"\n" +"The affinity is returned as a set of CPU identifiers."); + +#define OS_SCHED_GETAFFINITY_METHODDEF \ + {"sched_getaffinity", (PyCFunction)os_sched_getaffinity, METH_VARARGS, os_sched_getaffinity__doc__}, -PyDoc_STRVAR(posix_isatty__doc__, -"isatty(fd) -> bool\n\n\ -Return True if the file descriptor 'fd' is an open file descriptor\n\ -connected to the slave end of a terminal."); +static PyObject * +os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid); static PyObject * -posix_isatty(PyObject *self, PyObject *args) +os_sched_getaffinity(PyModuleDef *module, PyObject *args) { - int fd; - if (!PyArg_ParseTuple(args, "i:isatty", &fd)) - return NULL; - if (!_PyVerify_fd(fd)) - return PyBool_FromLong(0); - return PyBool_FromLong(isatty(fd)); -} + PyObject *return_value = NULL; + pid_t pid; -#ifdef HAVE_PIPE -PyDoc_STRVAR(posix_pipe__doc__, -"pipe() -> (read_end, write_end)\n\n\ -Create a pipe."); + if (!PyArg_ParseTuple(args, + "" _Py_PARSE_PID ":sched_getaffinity", + &pid)) + goto exit; + return_value = os_sched_getaffinity_impl(module, pid); + +exit: + return return_value; +} static PyObject * -posix_pipe(PyObject *self, PyObject *noargs) +os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid) +/*[clinic end generated code: output=7b273b0fca9830f0 input=eaf161936874b8a1]*/ { - int fds[2]; -#ifdef MS_WINDOWS - HANDLE read, write; - SECURITY_ATTRIBUTES attr; - BOOL ok; -#else - int res; -#endif - -#ifdef MS_WINDOWS - attr.nLength = sizeof(attr); - attr.lpSecurityDescriptor = NULL; - attr.bInheritHandle = FALSE; + int cpu, ncpus, count; + size_t setsize; + cpu_set_t *mask = NULL; + PyObject *res = NULL; - Py_BEGIN_ALLOW_THREADS - ok = CreatePipe(&read, &write, &attr, 0); - if (ok) { - fds[0] = _open_osfhandle((Py_intptr_t)read, _O_RDONLY); - fds[1] = _open_osfhandle((Py_intptr_t)write, _O_WRONLY); - if (fds[0] == -1 || fds[1] == -1) { - CloseHandle(read); - CloseHandle(write); - ok = 0; + ncpus = NCPUS_START; + while (1) { + setsize = CPU_ALLOC_SIZE(ncpus); + mask = CPU_ALLOC(ncpus); + if (mask == NULL) + return PyErr_NoMemory(); + if (sched_getaffinity(pid, setsize, mask) == 0) + break; + CPU_FREE(mask); + if (errno != EINVAL) + return posix_error(); + if (ncpus > INT_MAX / 2) { + PyErr_SetString(PyExc_OverflowError, "could not allocate " + "a large enough CPU set"); + return NULL; } + ncpus = ncpus * 2; } - Py_END_ALLOW_THREADS - - if (!ok) - return PyErr_SetFromWindowsErr(0); -#else - -#ifdef HAVE_PIPE2 - Py_BEGIN_ALLOW_THREADS - res = pipe2(fds, O_CLOEXEC); - Py_END_ALLOW_THREADS - if (res != 0 && errno == ENOSYS) - { -#endif - Py_BEGIN_ALLOW_THREADS - res = pipe(fds); - Py_END_ALLOW_THREADS - - if (res == 0) { - if (_Py_set_inheritable(fds[0], 0, NULL) < 0) { - close(fds[0]); - close(fds[1]); - return NULL; - } - if (_Py_set_inheritable(fds[1], 0, NULL) < 0) { - close(fds[0]); - close(fds[1]); - return NULL; + res = PySet_New(NULL); + if (res == NULL) + goto error; + for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { + if (CPU_ISSET_S(cpu, setsize, mask)) { + PyObject *cpu_num = PyLong_FromLong(cpu); + --count; + if (cpu_num == NULL) + goto error; + if (PySet_Add(res, cpu_num)) { + Py_DECREF(cpu_num); + goto error; } + Py_DECREF(cpu_num); } -#ifdef HAVE_PIPE2 } -#endif + CPU_FREE(mask); + return res; - if (res != 0) - return PyErr_SetFromErrno(PyExc_OSError); -#endif /* !MS_WINDOWS */ - return Py_BuildValue("(ii)", fds[0], fds[1]); +error: + if (mask) + CPU_FREE(mask); + Py_XDECREF(res); + return NULL; } -#endif /* HAVE_PIPE */ - -#ifdef HAVE_PIPE2 -PyDoc_STRVAR(posix_pipe2__doc__, -"pipe2(flags) -> (read_end, write_end)\n\n\ -Create a pipe with flags set atomically.\n\ -flags can be constructed by ORing together one or more of these values:\n\ -O_NONBLOCK, O_CLOEXEC.\n\ -"); - -static PyObject * -posix_pipe2(PyObject *self, PyObject *arg) -{ - int flags; - int fds[2]; - int res; - flags = _PyLong_AsInt(arg); - if (flags == -1 && PyErr_Occurred()) - return NULL; - - res = pipe2(fds, flags); - if (res != 0) - return posix_error(); - return Py_BuildValue("(ii)", fds[0], fds[1]); -} -#endif /* HAVE_PIPE2 */ +#endif /* HAVE_SCHED_SETAFFINITY */ -#ifdef HAVE_WRITEV -PyDoc_STRVAR(posix_writev__doc__, -"writev(fd, buffers) -> byteswritten\n\n\ -Write the contents of *buffers* to file descriptor *fd*. *buffers*\n\ -must be a sequence of bytes-like objects.\n\n\ -writev writes the contents of each object to the file descriptor\n\ -and returns the total number of bytes written."); +#endif /* HAVE_SCHED_H */ -static PyObject * -posix_writev(PyObject *self, PyObject *args) -{ - int fd, cnt; - Py_ssize_t res; - PyObject *seq; - struct iovec *iov; - Py_buffer *buf; - if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq)) - return NULL; - if (!PySequence_Check(seq)) { - PyErr_SetString(PyExc_TypeError, - "writev() arg 2 must be a sequence"); - return NULL; - } - cnt = PySequence_Size(seq); +#ifndef OS_SCHED_GET_PRIORITY_MAX_METHODDEF +#define OS_SCHED_GET_PRIORITY_MAX_METHODDEF +#endif /* OS_SCHED_GET_PRIORITY_MAX_METHODDEF */ - if (iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE) < 0) { - return NULL; - } +#ifndef OS_SCHED_GET_PRIORITY_MIN_METHODDEF +#define OS_SCHED_GET_PRIORITY_MIN_METHODDEF +#endif /* OS_SCHED_GET_PRIORITY_MIN_METHODDEF */ - Py_BEGIN_ALLOW_THREADS - res = writev(fd, iov, cnt); - Py_END_ALLOW_THREADS +#ifndef OS_SCHED_GETSCHEDULER_METHODDEF +#define OS_SCHED_GETSCHEDULER_METHODDEF +#endif /* OS_SCHED_GETSCHEDULER_METHODDEF */ - iov_cleanup(iov, buf, cnt); - if (res < 0) - return posix_error(); +#ifndef OS_SCHED_SETSCHEDULER_METHODDEF +#define OS_SCHED_SETSCHEDULER_METHODDEF +#endif /* OS_SCHED_SETSCHEDULER_METHODDEF */ - return PyLong_FromSsize_t(res); -} -#endif +#ifndef OS_SCHED_GETPARAM_METHODDEF +#define OS_SCHED_GETPARAM_METHODDEF +#endif /* OS_SCHED_GETPARAM_METHODDEF */ -#ifdef HAVE_PWRITE -PyDoc_STRVAR(posix_pwrite__doc__, -"pwrite(fd, string, offset) -> byteswritten\n\n\ -Write string to a file descriptor, fd, from offset, leaving the file\n\ -offset unchanged."); +#ifndef OS_SCHED_SETPARAM_METHODDEF +#define OS_SCHED_SETPARAM_METHODDEF +#endif /* OS_SCHED_SETPARAM_METHODDEF */ -static PyObject * -posix_pwrite(PyObject *self, PyObject *args) -{ - Py_buffer pbuf; - int fd; - off_t offset; - Py_ssize_t size; +#ifndef OS_SCHED_RR_GET_INTERVAL_METHODDEF +#define OS_SCHED_RR_GET_INTERVAL_METHODDEF +#endif /* OS_SCHED_RR_GET_INTERVAL_METHODDEF */ - if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &pbuf, _parse_off_t, &offset)) - return NULL; +#ifndef OS_SCHED_YIELD_METHODDEF +#define OS_SCHED_YIELD_METHODDEF +#endif /* OS_SCHED_YIELD_METHODDEF */ - if (!_PyVerify_fd(fd)) { - PyBuffer_Release(&pbuf); - return posix_error(); - } - Py_BEGIN_ALLOW_THREADS - size = pwrite(fd, pbuf.buf, (size_t)pbuf.len, offset); - Py_END_ALLOW_THREADS - PyBuffer_Release(&pbuf); - if (size < 0) - return posix_error(); - return PyLong_FromSsize_t(size); -} -#endif +#ifndef OS_SCHED_SETAFFINITY_METHODDEF +#define OS_SCHED_SETAFFINITY_METHODDEF +#endif /* OS_SCHED_SETAFFINITY_METHODDEF */ -#ifdef HAVE_MKFIFO -PyDoc_STRVAR(posix_mkfifo__doc__, -"mkfifo(path, mode=0o666, *, dir_fd=None)\n\n\ -Create a FIFO (a POSIX named pipe).\n\ -\n\ -If dir_fd is not None, it should be a file descriptor open to a directory,\n\ - and path should be relative; path will then be relative to that directory.\n\ -dir_fd may not be implemented on your platform.\n\ - If it is unavailable, using it will raise a NotImplementedError."); +#ifndef OS_SCHED_GETAFFINITY_METHODDEF +#define OS_SCHED_GETAFFINITY_METHODDEF +#endif /* OS_SCHED_GETAFFINITY_METHODDEF */ -static PyObject * -posix_mkfifo(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - int mode = 0666; - int dir_fd = DEFAULT_DIR_FD; - int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "mode", "dir_fd", NULL}; - memset(&path, 0, sizeof(path)); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkfifo", keywords, - path_converter, &path, - &mode, -#ifdef HAVE_MKFIFOAT - dir_fd_converter, &dir_fd +/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ +/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */ +#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) +#define DEV_PTY_FILE "/dev/ptc" +#define HAVE_DEV_PTMX #else - dir_fd_unavailable, &dir_fd -#endif - )) - return NULL; - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_MKFIFOAT - if (dir_fd != DEFAULT_DIR_FD) - result = mkfifoat(dir_fd, path.narrow, mode); - else -#endif - result = mkfifo(path.narrow, mode); - Py_END_ALLOW_THREADS - - if (result < 0) { - return_value = posix_error(); - goto exit; - } - - return_value = Py_None; - Py_INCREF(Py_None); - -exit: - path_cleanup(&path); - return return_value; -} +#define DEV_PTY_FILE "/dev/ptmx" #endif -#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) -PyDoc_STRVAR(posix_mknod__doc__, -"mknod(filename, mode=0o600, device=0, *, dir_fd=None)\n\n\ -Create a filesystem node (file, device special file or named pipe)\n\ -named filename. mode specifies both the permissions to use and the\n\ -type of node to be created, being combined (bitwise OR) with one of\n\ -S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\ -device defines the newly created device special file (probably using\n\ -os.makedev()), otherwise it is ignored.\n\ -\n\ -If dir_fd is not None, it should be a file descriptor open to a directory,\n\ - and path should be relative; path will then be relative to that directory.\n\ -dir_fd may not be implemented on your platform.\n\ - If it is unavailable, using it will raise a NotImplementedError."); - - -static PyObject * -posix_mknod(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - int mode = 0666; - dev_t device = 0; - int dir_fd = DEFAULT_DIR_FD; - int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "mode", "device", "dir_fd", NULL}; - - memset(&path, 0, sizeof(path)); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|iO&$O&:mknod", keywords, - path_converter, &path, - &mode, _Py_Dev_Converter, &device, -#ifdef HAVE_MKNODAT - dir_fd_converter, &dir_fd +#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) +#ifdef HAVE_PTY_H +#include #else - dir_fd_unavailable, &dir_fd +#ifdef HAVE_LIBUTIL_H +#include +#else +#ifdef HAVE_UTIL_H +#include +#endif /* HAVE_UTIL_H */ +#endif /* HAVE_LIBUTIL_H */ +#endif /* HAVE_PTY_H */ +#ifdef HAVE_STROPTS_H +#include #endif - )) - return NULL; +#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */ - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_MKNODAT - if (dir_fd != DEFAULT_DIR_FD) - result = mknodat(dir_fd, path.narrow, mode, device); - else -#endif - result = mknod(path.narrow, mode, device); - Py_END_ALLOW_THREADS - if (result < 0) { - return_value = posix_error(); - goto exit; - } +#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) +/*[clinic input] +os.openpty - return_value = Py_None; - Py_INCREF(Py_None); +Open a pseudo-terminal. -exit: - path_cleanup(&path); - return return_value; -} -#endif +Return a tuple of (master_fd, slave_fd) containing open file descriptors +for both the master and slave ends. +[clinic start generated code]*/ -#ifdef HAVE_DEVICE_MACROS -PyDoc_STRVAR(posix_major__doc__, -"major(device) -> major number\n\ -Extracts a device major number from a raw device number."); +PyDoc_STRVAR(os_openpty__doc__, +"openpty($module, /)\n" +"--\n" +"\n" +"Open a pseudo-terminal.\n" +"\n" +"Return a tuple of (master_fd, slave_fd) containing open file descriptors\n" +"for both the master and slave ends."); -static PyObject * -posix_major(PyObject *self, PyObject *args) -{ - dev_t device; - if (!PyArg_ParseTuple(args, "O&:major", _Py_Dev_Converter, &device)) - return NULL; - return PyLong_FromLong((long)major(device)); -} +#define OS_OPENPTY_METHODDEF \ + {"openpty", (PyCFunction)os_openpty, METH_NOARGS, os_openpty__doc__}, -PyDoc_STRVAR(posix_minor__doc__, -"minor(device) -> minor number\n\ -Extracts a device minor number from a raw device number."); +static PyObject * +os_openpty_impl(PyModuleDef *module); static PyObject * -posix_minor(PyObject *self, PyObject *args) +os_openpty(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) { - dev_t device; - if (!PyArg_ParseTuple(args, "O&:minor", _Py_Dev_Converter, &device)) - return NULL; - return PyLong_FromLong((long)minor(device)); + return os_openpty_impl(module); } -PyDoc_STRVAR(posix_makedev__doc__, -"makedev(major, minor) -> device number\n\ -Composes a raw device number from the major and minor device numbers."); - static PyObject * -posix_makedev(PyObject *self, PyObject *args) +os_openpty_impl(PyModuleDef *module) +/*[clinic end generated code: output=b12d3c1735468464 input=f3d99fd99e762907]*/ { - int major, minor; - if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor)) - return NULL; - return _PyLong_FromDev(makedev(major, minor)); -} -#endif /* device macros */ - + int master_fd = -1, slave_fd = -1; +#ifndef HAVE_OPENPTY + char * slave_name; +#endif +#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) + PyOS_sighandler_t sig_saved; +#ifdef sun + extern char *ptsname(int fildes); +#endif +#endif -#ifdef HAVE_FTRUNCATE -PyDoc_STRVAR(posix_ftruncate__doc__, -"ftruncate(fd, length)\n\n\ -Truncate a file to a specified length."); +#ifdef HAVE_OPENPTY + if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) + goto posix_error; -static PyObject * -posix_ftruncate(PyObject *self, PyObject *args) -{ - int fd; - off_t length; - int res; + if (_Py_set_inheritable(master_fd, 0, NULL) < 0) + goto error; + if (_Py_set_inheritable(slave_fd, 0, NULL) < 0) + goto error; - if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length)) - return NULL; +#elif defined(HAVE__GETPTY) + slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); + if (slave_name == NULL) + goto posix_error; + if (_Py_set_inheritable(master_fd, 0, NULL) < 0) + goto error; - Py_BEGIN_ALLOW_THREADS - res = ftruncate(fd, length); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - Py_INCREF(Py_None); - return Py_None; -} -#endif + slave_fd = _Py_open(slave_name, O_RDWR); + if (slave_fd < 0) + goto posix_error; -#ifdef HAVE_TRUNCATE -PyDoc_STRVAR(posix_truncate__doc__, -"truncate(path, length)\n\n\ -Truncate the file given by path to length bytes.\n\ -On some platforms, path may also be specified as an open file descriptor.\n\ - If this functionality is unavailable, using it raises an exception."); +#else + master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */ + if (master_fd < 0) + goto posix_error; -static PyObject * -posix_truncate(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - off_t length; - int res; - PyObject *result = NULL; - static char *keywords[] = {"path", "length", NULL}; + sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL); - memset(&path, 0, sizeof(path)); - path.function_name = "truncate"; -#ifdef HAVE_FTRUNCATE - path.allow_fd = 1; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", keywords, - path_converter, &path, - _parse_off_t, &length)) - return NULL; + /* change permission of slave */ + if (grantpt(master_fd) < 0) { + PyOS_setsig(SIGCHLD, sig_saved); + goto posix_error; + } - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FTRUNCATE - if (path.fd != -1) - res = ftruncate(path.fd, length); - else -#endif - res = truncate(path.narrow, length); - Py_END_ALLOW_THREADS - if (res < 0) - result = path_error(&path); - else { - Py_INCREF(Py_None); - result = Py_None; + /* unlock slave */ + if (unlockpt(master_fd) < 0) { + PyOS_setsig(SIGCHLD, sig_saved); + goto posix_error; } - path_cleanup(&path); - return result; -} -#endif -/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() - and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is - defined, which is the case in Python on AIX. AIX bug report: - http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ -#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) -# define POSIX_FADVISE_AIX_BUG -#endif + PyOS_setsig(SIGCHLD, sig_saved); -#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) -PyDoc_STRVAR(posix_posix_fallocate__doc__, -"posix_fallocate(fd, offset, len)\n\n\ -Ensures that enough disk space is allocated for the file specified by fd\n\ -starting from offset and continuing for len bytes."); + slave_name = ptsname(master_fd); /* get name of slave */ + if (slave_name == NULL) + goto posix_error; -static PyObject * -posix_posix_fallocate(PyObject *self, PyObject *args) -{ - off_t len, offset; - int res, fd; + slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ + if (slave_fd < 0) + goto posix_error; - if (!PyArg_ParseTuple(args, "iO&O&:posix_fallocate", - &fd, _parse_off_t, &offset, _parse_off_t, &len)) - return NULL; + if (_Py_set_inheritable(master_fd, 0, NULL) < 0) + goto posix_error; - Py_BEGIN_ALLOW_THREADS - res = posix_fallocate(fd, offset, len); - Py_END_ALLOW_THREADS - if (res != 0) { - errno = res; - return posix_error(); - } - Py_RETURN_NONE; -} +#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) + ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ + ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ +#ifndef __hpux + ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ +#endif /* __hpux */ +#endif /* HAVE_CYGWIN */ +#endif /* HAVE_OPENPTY */ + + return Py_BuildValue("(ii)", master_fd, slave_fd); + +posix_error: + posix_error(); +#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) +error: #endif + if (master_fd != -1) + close(master_fd); + if (slave_fd != -1) + close(slave_fd); + return NULL; +} +#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ -#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) -PyDoc_STRVAR(posix_posix_fadvise__doc__, -"posix_fadvise(fd, offset, len, advice)\n\n\ -Announces an intention to access data in a specific pattern thus allowing\n\ -the kernel to make optimizations.\n\ -The advice applies to the region of the file specified by fd starting at\n\ -offset and continuing for len bytes.\n\ -advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n\ -POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED or\n\ -POSIX_FADV_DONTNEED."); -static PyObject * -posix_posix_fadvise(PyObject *self, PyObject *args) -{ - off_t len, offset; - int res, fd, advice; +#ifdef HAVE_FORKPTY +/*[clinic input] +os.forkpty - if (!PyArg_ParseTuple(args, "iO&O&i:posix_fadvise", - &fd, _parse_off_t, &offset, _parse_off_t, &len, &advice)) - return NULL; +Fork a new process with a new pseudo-terminal as controlling tty. - Py_BEGIN_ALLOW_THREADS - res = posix_fadvise(fd, offset, len, advice); - Py_END_ALLOW_THREADS - if (res != 0) { - errno = res; - return posix_error(); - } - Py_RETURN_NONE; -} -#endif +Returns a tuple of (pid, master_fd). +Like fork(), return pid of 0 to the child process, +and pid of child to the parent process. +To both, return fd of newly opened pseudo-terminal. +[clinic start generated code]*/ -#ifdef HAVE_PUTENV -PyDoc_STRVAR(posix_putenv__doc__, -"putenv(key, value)\n\n\ -Change or add an environment variable."); +PyDoc_STRVAR(os_forkpty__doc__, +"forkpty($module, /)\n" +"--\n" +"\n" +"Fork a new process with a new pseudo-terminal as controlling tty.\n" +"\n" +"Returns a tuple of (pid, master_fd).\n" +"Like fork(), return pid of 0 to the child process,\n" +"and pid of child to the parent process.\n" +"To both, return fd of newly opened pseudo-terminal."); -/* Save putenv() parameters as values here, so we can collect them when they - * get re-set with another call for the same key. */ -static PyObject *posix_putenv_garbage; +#define OS_FORKPTY_METHODDEF \ + {"forkpty", (PyCFunction)os_forkpty, METH_NOARGS, os_forkpty__doc__}, static PyObject * -posix_putenv(PyObject *self, PyObject *args) +os_forkpty_impl(PyModuleDef *module); + +static PyObject * +os_forkpty(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) { - PyObject *newstr = NULL; -#ifdef MS_WINDOWS - PyObject *os1, *os2; - wchar_t *newenv; + return os_forkpty_impl(module); +} - if (!PyArg_ParseTuple(args, - "UU:putenv", - &os1, &os2)) - return NULL; +static PyObject * +os_forkpty_impl(PyModuleDef *module) +/*[clinic end generated code: output=d4f82958d2ed5cad input=f1f7f4bae3966010]*/ +{ + int master_fd = -1, result = 0; + pid_t pid; - newstr = PyUnicode_FromFormat("%U=%U", os1, os2); - if (newstr == NULL) { - PyErr_NoMemory(); - goto error; + _PyImport_AcquireLock(); + pid = forkpty(&master_fd, NULL, NULL, NULL); + if (pid == 0) { + /* child: this clobbers and resets the import lock. */ + PyOS_AfterFork(); + } else { + /* parent: release the import lock. */ + result = _PyImport_ReleaseLock(); } - if (_MAX_ENV < PyUnicode_GET_LENGTH(newstr)) { - PyErr_Format(PyExc_ValueError, - "the environment variable is longer than %u characters", - _MAX_ENV); - goto error; + if (pid == -1) + return posix_error(); + if (result < 0) { + /* Don't clobber the OSError if the fork failed. */ + PyErr_SetString(PyExc_RuntimeError, + "not holding the import lock"); + return NULL; } + return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); +} +#endif /* HAVE_FORKPTY */ - newenv = PyUnicode_AsUnicode(newstr); - if (newenv == NULL) - goto error; - if (_wputenv(newenv)) { - posix_error(); - goto error; - } -#else - PyObject *os1, *os2; - char *s1, *s2; - char *newenv; - if (!PyArg_ParseTuple(args, - "O&O&:putenv", - PyUnicode_FSConverter, &os1, - PyUnicode_FSConverter, &os2)) - return NULL; - s1 = PyBytes_AsString(os1); - s2 = PyBytes_AsString(os2); +#ifdef HAVE_GETEGID +/*[clinic input] +os.getegid - newstr = PyBytes_FromFormat("%s=%s", s1, s2); - if (newstr == NULL) { - PyErr_NoMemory(); - goto error; - } +Return the current process's effective group id. +[clinic start generated code]*/ - newenv = PyBytes_AS_STRING(newstr); - if (putenv(newenv)) { - posix_error(); - goto error; - } -#endif +PyDoc_STRVAR(os_getegid__doc__, +"getegid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s effective group id."); - /* Install the first arg and newstr in posix_putenv_garbage; - * this will cause previous value to be collected. This has to - * happen after the real putenv() call because the old value - * was still accessible until then. */ - if (PyDict_SetItem(posix_putenv_garbage, os1, newstr)) { - /* really not much we can do; just leak */ - PyErr_Clear(); - } - else { - Py_DECREF(newstr); - } +#define OS_GETEGID_METHODDEF \ + {"getegid", (PyCFunction)os_getegid, METH_NOARGS, os_getegid__doc__}, -#ifndef MS_WINDOWS - Py_DECREF(os1); - Py_DECREF(os2); -#endif - Py_RETURN_NONE; +static PyObject * +os_getegid_impl(PyModuleDef *module); -error: -#ifndef MS_WINDOWS - Py_DECREF(os1); - Py_DECREF(os2); -#endif - Py_XDECREF(newstr); - return NULL; +static PyObject * +os_getegid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getegid_impl(module); } -#endif /* putenv */ - -#ifdef HAVE_UNSETENV -PyDoc_STRVAR(posix_unsetenv__doc__, -"unsetenv(key)\n\n\ -Delete an environment variable."); static PyObject * -posix_unsetenv(PyObject *self, PyObject *args) +os_getegid_impl(PyModuleDef *module) +/*[clinic end generated code: output=fd12c346fa41cccb input=1596f79ad1107d5d]*/ { - PyObject *name; -#ifndef HAVE_BROKEN_UNSETENV - int err; -#endif + return _PyLong_FromGid(getegid()); +} +#endif /* HAVE_GETEGID */ - if (!PyArg_ParseTuple(args, "O&:unsetenv", - PyUnicode_FSConverter, &name)) - return NULL; +#ifdef HAVE_GETEUID +/*[clinic input] +os.geteuid -#ifdef HAVE_BROKEN_UNSETENV - unsetenv(PyBytes_AS_STRING(name)); -#else - err = unsetenv(PyBytes_AS_STRING(name)); - if (err) { - Py_DECREF(name); - return posix_error(); - } -#endif +Return the current process's effective user id. +[clinic start generated code]*/ - /* Remove the key from posix_putenv_garbage; - * this will cause it to be collected. This has to - * happen after the real unsetenv() call because the - * old value was still accessible until then. - */ - if (PyDict_DelItem(posix_putenv_garbage, name)) { - /* really not much we can do; just leak */ - PyErr_Clear(); - } - Py_DECREF(name); - Py_RETURN_NONE; -} -#endif /* unsetenv */ +PyDoc_STRVAR(os_geteuid__doc__, +"geteuid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s effective user id."); + +#define OS_GETEUID_METHODDEF \ + {"geteuid", (PyCFunction)os_geteuid, METH_NOARGS, os_geteuid__doc__}, -PyDoc_STRVAR(posix_strerror__doc__, -"strerror(code) -> string\n\n\ -Translate an error code to a message string."); +static PyObject * +os_geteuid_impl(PyModuleDef *module); static PyObject * -posix_strerror(PyObject *self, PyObject *args) +os_geteuid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) { - int code; - char *message; - if (!PyArg_ParseTuple(args, "i:strerror", &code)) - return NULL; - message = strerror(code); - if (message == NULL) { - PyErr_SetString(PyExc_ValueError, - "strerror() argument out of range"); - return NULL; - } - return PyUnicode_DecodeLocale(message, "surrogateescape"); + return os_geteuid_impl(module); } - -#ifdef HAVE_SYS_WAIT_H - -#ifdef WCOREDUMP -PyDoc_STRVAR(posix_WCOREDUMP__doc__, -"WCOREDUMP(status) -> bool\n\n\ -Return True if the process returning 'status' was dumped to a core file."); - static PyObject * -posix_WCOREDUMP(PyObject *self, PyObject *args) +os_geteuid_impl(PyModuleDef *module) +/*[clinic end generated code: output=03d98e07f4bc03d4 input=4644c662d3bd9f19]*/ { - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status))) - return NULL; - - return PyBool_FromLong(WCOREDUMP(status)); + return _PyLong_FromUid(geteuid()); } -#endif /* WCOREDUMP */ +#endif /* HAVE_GETEUID */ -#ifdef WIFCONTINUED -PyDoc_STRVAR(posix_WIFCONTINUED__doc__, -"WIFCONTINUED(status) -> bool\n\n\ -Return True if the process returning 'status' was continued from a\n\ -job control stop."); -static PyObject * -posix_WIFCONTINUED(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; +#ifdef HAVE_GETGID +/*[clinic input] +os.getgid - if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status))) - return NULL; +Return the current process's group id. +[clinic start generated code]*/ - return PyBool_FromLong(WIFCONTINUED(status)); -} -#endif /* WIFCONTINUED */ +PyDoc_STRVAR(os_getgid__doc__, +"getgid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s group id."); -#ifdef WIFSTOPPED -PyDoc_STRVAR(posix_WIFSTOPPED__doc__, -"WIFSTOPPED(status) -> bool\n\n\ -Return True if the process returning 'status' was stopped."); +#define OS_GETGID_METHODDEF \ + {"getgid", (PyCFunction)os_getgid, METH_NOARGS, os_getgid__doc__}, static PyObject * -posix_WIFSTOPPED(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status))) - return NULL; +os_getgid_impl(PyModuleDef *module); - return PyBool_FromLong(WIFSTOPPED(status)); +static PyObject * +os_getgid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getgid_impl(module); } -#endif /* WIFSTOPPED */ - -#ifdef WIFSIGNALED -PyDoc_STRVAR(posix_WIFSIGNALED__doc__, -"WIFSIGNALED(status) -> bool\n\n\ -Return True if the process returning 'status' was terminated by a signal."); static PyObject * -posix_WIFSIGNALED(PyObject *self, PyObject *args) +os_getgid_impl(PyModuleDef *module) +/*[clinic end generated code: output=07b0356121b8098d input=58796344cd87c0f6]*/ { - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status))) - return NULL; - - return PyBool_FromLong(WIFSIGNALED(status)); + return _PyLong_FromGid(getgid()); } -#endif /* WIFSIGNALED */ +#endif /* HAVE_GETGID */ -#ifdef WIFEXITED -PyDoc_STRVAR(posix_WIFEXITED__doc__, -"WIFEXITED(status) -> bool\n\n\ -Return true if the process returning 'status' exited using the exit()\n\ -system call."); -static PyObject * -posix_WIFEXITED(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; +/*[clinic input] +os.getpid - if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status))) - return NULL; +Return the current process id. +[clinic start generated code]*/ - return PyBool_FromLong(WIFEXITED(status)); -} -#endif /* WIFEXITED */ +PyDoc_STRVAR(os_getpid__doc__, +"getpid($module, /)\n" +"--\n" +"\n" +"Return the current process id."); -#ifdef WEXITSTATUS -PyDoc_STRVAR(posix_WEXITSTATUS__doc__, -"WEXITSTATUS(status) -> integer\n\n\ -Return the process return code from 'status'."); +#define OS_GETPID_METHODDEF \ + {"getpid", (PyCFunction)os_getpid, METH_NOARGS, os_getpid__doc__}, static PyObject * -posix_WEXITSTATUS(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; +os_getpid_impl(PyModuleDef *module); - if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status))) - return NULL; - - return Py_BuildValue("i", WEXITSTATUS(status)); +static PyObject * +os_getpid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getpid_impl(module); } -#endif /* WEXITSTATUS */ - -#ifdef WTERMSIG -PyDoc_STRVAR(posix_WTERMSIG__doc__, -"WTERMSIG(status) -> integer\n\n\ -Return the signal that terminated the process that provided the 'status'\n\ -value."); static PyObject * -posix_WTERMSIG(PyObject *self, PyObject *args) +os_getpid_impl(PyModuleDef *module) +/*[clinic end generated code: output=d63a01a3cebc573d input=5a9a00f0ab68aa00]*/ { - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status))) - return NULL; - - return Py_BuildValue("i", WTERMSIG(status)); + return PyLong_FromPid(getpid()); } -#endif /* WTERMSIG */ -#ifdef WSTOPSIG -PyDoc_STRVAR(posix_WSTOPSIG__doc__, -"WSTOPSIG(status) -> integer\n\n\ -Return the signal that stopped the process that provided\n\ -the 'status' value."); +#ifdef HAVE_GETGROUPLIST + +/* AC 3.5: funny apple logic below */ +PyDoc_STRVAR(posix_getgrouplist__doc__, +"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\ +Returns a list of groups to which a user belongs.\n\n\ + user: username to lookup\n\ + group: base group id of the user"); static PyObject * -posix_WSTOPSIG(PyObject *self, PyObject *args) +posix_getgrouplist(PyObject *self, PyObject *args) { - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status))) - return NULL; - - return Py_BuildValue("i", WSTOPSIG(status)); -} -#endif /* WSTOPSIG */ +#ifdef NGROUPS_MAX +#define MAX_GROUPS NGROUPS_MAX +#else + /* defined to be 16 on Solaris7, so this should be a small number */ +#define MAX_GROUPS 64 +#endif -#endif /* HAVE_SYS_WAIT_H */ + const char *user; + int i, ngroups; + PyObject *list; +#ifdef __APPLE__ + int *groups, basegid; +#else + gid_t *groups, basegid; +#endif + ngroups = MAX_GROUPS; +#ifdef __APPLE__ + if (!PyArg_ParseTuple(args, "si:getgrouplist", &user, &basegid)) + return NULL; +#else + if (!PyArg_ParseTuple(args, "sO&:getgrouplist", &user, + _Py_Gid_Converter, &basegid)) + return NULL; +#endif -#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) -#ifdef _SCO_DS -/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the - needed definitions in sys/statvfs.h */ -#define _SVID3 +#ifdef __APPLE__ - groups = PyMem_Malloc(ngroups * sizeof(int)); ++ groups = PyMem_New(int, ngroups); +#else - groups = PyMem_Malloc(ngroups * sizeof(gid_t)); ++ groups = PyMem_New(gid_t, ngroups); #endif -#include + if (groups == NULL) + return PyErr_NoMemory(); -static PyObject* -_pystatvfs_fromstructstatvfs(struct statvfs st) { - PyObject *v = PyStructSequence_New(&StatVFSResultType); - if (v == NULL) + if (getgrouplist(user, basegid, groups, &ngroups) == -1) { + PyMem_Del(groups); + return posix_error(); + } + + list = PyList_New(ngroups); + if (list == NULL) { + PyMem_Del(groups); return NULL; + } -#if !defined(HAVE_LARGEFILE_SUPPORT) - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); - PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks)); - PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree)); - PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail)); - PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files)); - PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree)); - PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail)); - PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); - PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); + for (i = 0; i < ngroups; i++) { +#ifdef __APPLE__ + PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]); #else - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); - PyStructSequence_SET_ITEM(v, 2, - PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks)); - PyStructSequence_SET_ITEM(v, 3, - PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree)); - PyStructSequence_SET_ITEM(v, 4, - PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail)); - PyStructSequence_SET_ITEM(v, 5, - PyLong_FromLongLong((PY_LONG_LONG) st.f_files)); - PyStructSequence_SET_ITEM(v, 6, - PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree)); - PyStructSequence_SET_ITEM(v, 7, - PyLong_FromLongLong((PY_LONG_LONG) st.f_favail)); - PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); - PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); + PyObject *o = _PyLong_FromGid(groups[i]); #endif - if (PyErr_Occurred()) { - Py_DECREF(v); - return NULL; + if (o == NULL) { + Py_DECREF(list); + PyMem_Del(groups); + return NULL; + } + PyList_SET_ITEM(list, i, o); } - return v; -} + PyMem_Del(groups); -PyDoc_STRVAR(posix_fstatvfs__doc__, -"fstatvfs(fd) -> statvfs result\n\n\ -Perform an fstatvfs system call on the given fd.\n\ -Equivalent to statvfs(fd)."); + return list; +} +#endif /* HAVE_GETGROUPLIST */ -static PyObject * -posix_fstatvfs(PyObject *self, PyObject *args) -{ - int fd, res; - struct statvfs st; - if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd)) - return NULL; - Py_BEGIN_ALLOW_THREADS - res = fstatvfs(fd, &st); - Py_END_ALLOW_THREADS - if (res != 0) - return posix_error(); +#ifdef HAVE_GETGROUPS +/*[clinic input] +os.getgroups - return _pystatvfs_fromstructstatvfs(st); -} -#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */ +Return list of supplemental group IDs for the process. +[clinic start generated code]*/ +PyDoc_STRVAR(os_getgroups__doc__, +"getgroups($module, /)\n" +"--\n" +"\n" +"Return list of supplemental group IDs for the process."); -#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) -#include +#define OS_GETGROUPS_METHODDEF \ + {"getgroups", (PyCFunction)os_getgroups, METH_NOARGS, os_getgroups__doc__}, -PyDoc_STRVAR(posix_statvfs__doc__, -"statvfs(path)\n\n\ -Perform a statvfs system call on the given path.\n\ -\n\ -path may always be specified as a string.\n\ -On some platforms, path may also be specified as an open file descriptor.\n\ - If this functionality is unavailable, using it raises an exception."); +static PyObject * +os_getgroups_impl(PyModuleDef *module); static PyObject * -posix_statvfs(PyObject *self, PyObject *args, PyObject *kwargs) +os_getgroups(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) { - static char *keywords[] = {"path", NULL}; - path_t path; - int result; - PyObject *return_value = NULL; - struct statvfs st; - - memset(&path, 0, sizeof(path)); - path.function_name = "statvfs"; -#ifdef HAVE_FSTATVFS - path.allow_fd = 1; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:statvfs", keywords, - path_converter, &path - )) - return NULL; - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FSTATVFS - if (path.fd != -1) { -#ifdef __APPLE__ - /* handle weak-linking on Mac OS X 10.3 */ - if (fstatvfs == NULL) { - fd_specified("statvfs", path.fd); - goto exit; - } -#endif - result = fstatvfs(path.fd, &st); - } - else -#endif - result = statvfs(path.narrow, &st); - Py_END_ALLOW_THREADS - - if (result) { - return_value = path_error(&path); - goto exit; - } - - return_value = _pystatvfs_fromstructstatvfs(st); - -exit: - path_cleanup(&path); - return return_value; + return os_getgroups_impl(module); } -#endif /* HAVE_STATVFS */ - -#ifdef MS_WINDOWS -PyDoc_STRVAR(win32__getdiskusage__doc__, -"_getdiskusage(path) -> (total, free)\n\n\ -Return disk usage statistics about the given path as (total, free) tuple."); static PyObject * -win32__getdiskusage(PyObject *self, PyObject *args) +os_getgroups_impl(PyModuleDef *module) +/*[clinic end generated code: output=d9a3559b2e6f4ab8 input=d3f109412e6a155c]*/ { - BOOL retval; - ULARGE_INTEGER _, total, free; - const wchar_t *path; + PyObject *result = NULL; - if (! PyArg_ParseTuple(args, "u", &path)) - return NULL; +#ifdef NGROUPS_MAX +#define MAX_GROUPS NGROUPS_MAX +#else + /* defined to be 16 on Solaris7, so this should be a small number */ +#define MAX_GROUPS 64 +#endif + gid_t grouplist[MAX_GROUPS]; - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW(path, &_, &total, &free); - Py_END_ALLOW_THREADS - if (retval == 0) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); -} -#endif - - -/* This is used for fpathconf(), pathconf(), confstr() and sysconf(). - * It maps strings representing configuration variable names to - * integer values, allowing those functions to be called with the - * magic names instead of polluting the module's namespace with tons of - * rarely-used constants. There are three separate tables that use - * these definitions. - * - * This code is always included, even if none of the interfaces that - * need it are included. The #if hackery needed to avoid it would be - * sufficiently pervasive that it's not worth the loss of readability. - */ -struct constdef { - char *name; - long value; -}; + /* On MacOSX getgroups(2) can return more than MAX_GROUPS results + * This is a helper variable to store the intermediate result when + * that happens. + * + * To keep the code readable the OSX behaviour is unconditional, + * according to the POSIX spec this should be safe on all unix-y + * systems. + */ + gid_t* alt_grouplist = grouplist; + int n; -static int -conv_confname(PyObject *arg, int *valuep, struct constdef *table, - size_t tablesize) -{ - if (PyLong_Check(arg)) { - *valuep = PyLong_AS_LONG(arg); - return 1; +#ifdef __APPLE__ + /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if + * there are more groups than can fit in grouplist. Therefore, on OS X + * always first call getgroups with length 0 to get the actual number + * of groups. + */ + n = getgroups(0, NULL); + if (n < 0) { + return posix_error(); + } else if (n <= MAX_GROUPS) { + /* groups will fit in existing array */ + alt_grouplist = grouplist; + } else { - alt_grouplist = PyMem_Malloc(n * sizeof(gid_t)); ++ alt_grouplist = PyMem_New(gid_t, n); + if (alt_grouplist == NULL) { + errno = EINVAL; + return posix_error(); + } } - else { - /* look up the value in the table using a binary search */ - size_t lo = 0; - size_t mid; - size_t hi = tablesize; - int cmp; - const char *confname; - if (!PyUnicode_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "configuration names must be strings or integers"); - return 0; + + n = getgroups(n, alt_grouplist); + if (n == -1) { + if (alt_grouplist != grouplist) { + PyMem_Free(alt_grouplist); } - confname = _PyUnicode_AsString(arg); - if (confname == NULL) - return 0; - while (lo < hi) { - mid = (lo + hi) / 2; - cmp = strcmp(confname, table[mid].name); - if (cmp < 0) - hi = mid; - else if (cmp > 0) - lo = mid + 1; - else { - *valuep = table[mid].value; - return 1; + return posix_error(); + } +#else + n = getgroups(MAX_GROUPS, grouplist); + if (n < 0) { + if (errno == EINVAL) { + n = getgroups(0, NULL); + if (n == -1) { + return posix_error(); + } + if (n == 0) { + /* Avoid malloc(0) */ + alt_grouplist = grouplist; + } else { - alt_grouplist = PyMem_Malloc(n * sizeof(gid_t)); ++ alt_grouplist = PyMem_New(gid_t, n); + if (alt_grouplist == NULL) { + errno = EINVAL; + return posix_error(); + } + n = getgroups(n, alt_grouplist); + if (n == -1) { + PyMem_Free(alt_grouplist); + return posix_error(); + } } + } else { + return posix_error(); } - PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); - return 0; } -} - - -#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) -static struct constdef posix_constants_pathconf[] = { -#ifdef _PC_ABI_AIO_XFER_MAX - {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, -#endif -#ifdef _PC_ABI_ASYNC_IO - {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, -#endif -#ifdef _PC_ASYNC_IO - {"PC_ASYNC_IO", _PC_ASYNC_IO}, -#endif -#ifdef _PC_CHOWN_RESTRICTED - {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, -#endif -#ifdef _PC_FILESIZEBITS - {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, -#endif -#ifdef _PC_LAST - {"PC_LAST", _PC_LAST}, -#endif -#ifdef _PC_LINK_MAX - {"PC_LINK_MAX", _PC_LINK_MAX}, -#endif -#ifdef _PC_MAX_CANON - {"PC_MAX_CANON", _PC_MAX_CANON}, -#endif -#ifdef _PC_MAX_INPUT - {"PC_MAX_INPUT", _PC_MAX_INPUT}, -#endif -#ifdef _PC_NAME_MAX - {"PC_NAME_MAX", _PC_NAME_MAX}, -#endif -#ifdef _PC_NO_TRUNC - {"PC_NO_TRUNC", _PC_NO_TRUNC}, -#endif -#ifdef _PC_PATH_MAX - {"PC_PATH_MAX", _PC_PATH_MAX}, -#endif -#ifdef _PC_PIPE_BUF - {"PC_PIPE_BUF", _PC_PIPE_BUF}, -#endif -#ifdef _PC_PRIO_IO - {"PC_PRIO_IO", _PC_PRIO_IO}, -#endif -#ifdef _PC_SOCK_MAXBUF - {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, -#endif -#ifdef _PC_SYNC_IO - {"PC_SYNC_IO", _PC_SYNC_IO}, -#endif -#ifdef _PC_VDISABLE - {"PC_VDISABLE", _PC_VDISABLE}, -#endif -#ifdef _PC_ACL_ENABLED - {"PC_ACL_ENABLED", _PC_ACL_ENABLED}, -#endif -#ifdef _PC_MIN_HOLE_SIZE - {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE}, -#endif -#ifdef _PC_ALLOC_SIZE_MIN - {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN}, -#endif -#ifdef _PC_REC_INCR_XFER_SIZE - {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE}, -#endif -#ifdef _PC_REC_MAX_XFER_SIZE - {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE}, -#endif -#ifdef _PC_REC_MIN_XFER_SIZE - {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE}, -#endif -#ifdef _PC_REC_XFER_ALIGN - {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN}, -#endif -#ifdef _PC_SYMLINK_MAX - {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX}, -#endif -#ifdef _PC_XATTR_ENABLED - {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED}, -#endif -#ifdef _PC_XATTR_EXISTS - {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, -#endif -#ifdef _PC_TIMESTAMP_RESOLUTION - {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, -#endif -}; - -static int -conv_path_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_pathconf, - sizeof(posix_constants_pathconf) - / sizeof(struct constdef)); -} #endif -#ifdef HAVE_FPATHCONF -PyDoc_STRVAR(posix_fpathconf__doc__, -"fpathconf(fd, name) -> integer\n\n\ -Return the configuration limit name for the file descriptor fd.\n\ -If there is no limit, return -1."); - -static PyObject * -posix_fpathconf(PyObject *self, PyObject *args) -{ - PyObject *result = NULL; - int name, fd; - - if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd, - conv_path_confname, &name)) { - long limit; + result = PyList_New(n); + if (result != NULL) { + int i; + for (i = 0; i < n; ++i) { + PyObject *o = _PyLong_FromGid(alt_grouplist[i]); + if (o == NULL) { + Py_DECREF(result); + result = NULL; + break; + } + PyList_SET_ITEM(result, i, o); + } + } - errno = 0; - limit = fpathconf(fd, name); - if (limit == -1 && errno != 0) - posix_error(); - else - result = PyLong_FromLong(limit); + if (alt_grouplist != grouplist) { + PyMem_Free(alt_grouplist); } + return result; } -#endif +#endif /* HAVE_GETGROUPS */ +#ifdef HAVE_INITGROUPS +PyDoc_STRVAR(posix_initgroups__doc__, +"initgroups(username, gid) -> None\n\n\ +Call the system initgroups() to initialize the group access list with all of\n\ +the groups of which the specified username is a member, plus the specified\n\ +group id."); -#ifdef HAVE_PATHCONF -PyDoc_STRVAR(posix_pathconf__doc__, -"pathconf(path, name) -> integer\n\n\ -Return the configuration limit name for the file or directory path.\n\ -If there is no limit, return -1.\n\ -On some platforms, path may also be specified as an open file descriptor.\n\ - If this functionality is unavailable, using it raises an exception."); - +/* AC 3.5: funny apple logic */ static PyObject * -posix_pathconf(PyObject *self, PyObject *args, PyObject *kwargs) +posix_initgroups(PyObject *self, PyObject *args) { - path_t path; - PyObject *result = NULL; - int name; - static char *keywords[] = {"path", "name", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "pathconf"; -#ifdef HAVE_FPATHCONF - path.allow_fd = 1; + PyObject *oname; + char *username; + int res; +#ifdef __APPLE__ + int gid; +#else + gid_t gid; #endif - if (PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:pathconf", keywords, - path_converter, &path, - conv_path_confname, &name)) { - long limit; - errno = 0; -#ifdef HAVE_FPATHCONF - if (path.fd != -1) - limit = fpathconf(path.fd, name); - else -#endif - limit = pathconf(path.narrow, name); - if (limit == -1 && errno != 0) { - if (errno == EINVAL) - /* could be a path or name problem */ - posix_error(); - else - result = path_error(&path); - } - else - result = PyLong_FromLong(limit); - } - path_cleanup(&path); - return result; -} +#ifdef __APPLE__ + if (!PyArg_ParseTuple(args, "O&i:initgroups", + PyUnicode_FSConverter, &oname, + &gid)) +#else + if (!PyArg_ParseTuple(args, "O&O&:initgroups", + PyUnicode_FSConverter, &oname, + _Py_Gid_Converter, &gid)) #endif + return NULL; + username = PyBytes_AS_STRING(oname); -#ifdef HAVE_CONFSTR -static struct constdef posix_constants_confstr[] = { -#ifdef _CS_ARCHITECTURE - {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, -#endif -#ifdef _CS_GNU_LIBC_VERSION - {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION}, -#endif -#ifdef _CS_GNU_LIBPTHREAD_VERSION - {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION}, -#endif -#ifdef _CS_HOSTNAME - {"CS_HOSTNAME", _CS_HOSTNAME}, -#endif -#ifdef _CS_HW_PROVIDER - {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, -#endif -#ifdef _CS_HW_SERIAL - {"CS_HW_SERIAL", _CS_HW_SERIAL}, -#endif -#ifdef _CS_INITTAB_NAME - {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, -#endif -#ifdef _CS_LFS64_CFLAGS - {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, -#endif -#ifdef _CS_LFS64_LDFLAGS - {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, -#endif -#ifdef _CS_LFS64_LIBS - {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, -#endif -#ifdef _CS_LFS64_LINTFLAGS - {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, -#endif -#ifdef _CS_LFS_CFLAGS - {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, -#endif -#ifdef _CS_LFS_LDFLAGS - {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, -#endif -#ifdef _CS_LFS_LIBS - {"CS_LFS_LIBS", _CS_LFS_LIBS}, -#endif -#ifdef _CS_LFS_LINTFLAGS - {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, -#endif -#ifdef _CS_MACHINE - {"CS_MACHINE", _CS_MACHINE}, -#endif -#ifdef _CS_PATH - {"CS_PATH", _CS_PATH}, -#endif -#ifdef _CS_RELEASE - {"CS_RELEASE", _CS_RELEASE}, -#endif -#ifdef _CS_SRPC_DOMAIN - {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, -#endif -#ifdef _CS_SYSNAME - {"CS_SYSNAME", _CS_SYSNAME}, -#endif -#ifdef _CS_VERSION - {"CS_VERSION", _CS_VERSION}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS - {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS - {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LIBS - {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS - {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS - {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS - {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS - {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS - {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_CFLAGS - {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS - {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LIBS - {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS - {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS - {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS - {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS - {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS - {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, -#endif -#ifdef _MIPS_CS_AVAIL_PROCESSORS - {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, -#endif -#ifdef _MIPS_CS_BASE - {"MIPS_CS_BASE", _MIPS_CS_BASE}, -#endif -#ifdef _MIPS_CS_HOSTID - {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, -#endif -#ifdef _MIPS_CS_HW_NAME - {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, -#endif -#ifdef _MIPS_CS_NUM_PROCESSORS - {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, -#endif -#ifdef _MIPS_CS_OSREL_MAJ - {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, -#endif -#ifdef _MIPS_CS_OSREL_MIN - {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, -#endif -#ifdef _MIPS_CS_OSREL_PATCH - {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, -#endif -#ifdef _MIPS_CS_OS_NAME - {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, -#endif -#ifdef _MIPS_CS_OS_PROVIDER - {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, -#endif -#ifdef _MIPS_CS_PROCESSORS - {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, -#endif -#ifdef _MIPS_CS_SERIAL - {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, -#endif -#ifdef _MIPS_CS_VENDOR - {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, -#endif -}; + res = initgroups(username, gid); + Py_DECREF(oname); + if (res == -1) + return PyErr_SetFromErrno(PyExc_OSError); -static int -conv_confstr_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_confstr, - sizeof(posix_constants_confstr) - / sizeof(struct constdef)); + Py_INCREF(Py_None); + return Py_None; } +#endif /* HAVE_INITGROUPS */ + + +#ifdef HAVE_GETPGID +/*[clinic input] +os.getpgid + + pid: pid_t + +Call the system call getpgid(), and return the result. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_getpgid__doc__, +"getpgid($module, /, pid)\n" +"--\n" +"\n" +"Call the system call getpgid(), and return the result."); -PyDoc_STRVAR(posix_confstr__doc__, -"confstr(name) -> string\n\n\ -Return a string-valued system configuration variable."); +#define OS_GETPGID_METHODDEF \ + {"getpgid", (PyCFunction)os_getpgid, METH_VARARGS|METH_KEYWORDS, os_getpgid__doc__}, + +static PyObject * +os_getpgid_impl(PyModuleDef *module, pid_t pid); static PyObject * -posix_confstr(PyObject *self, PyObject *args) +os_getpgid(PyModuleDef *module, PyObject *args, PyObject *kwargs) { - PyObject *result = NULL; - int name; - char buffer[255]; - size_t len; + PyObject *return_value = NULL; + static char *_keywords[] = {"pid", NULL}; + pid_t pid; - if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) - return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "" _Py_PARSE_PID ":getpgid", _keywords, + &pid)) + goto exit; + return_value = os_getpgid_impl(module, pid); - errno = 0; - len = confstr(name, buffer, sizeof(buffer)); - if (len == 0) { - if (errno) { - posix_error(); - return NULL; - } - else { - Py_RETURN_NONE; - } - } +exit: + return return_value; +} - if (len >= sizeof(buffer)) { - char *buf = PyMem_Malloc(len); - if (buf == NULL) - return PyErr_NoMemory(); - confstr(name, buf, len); - result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1); - PyMem_Free(buf); - } - else - result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); - return result; +static PyObject * +os_getpgid_impl(PyModuleDef *module, pid_t pid) +/*[clinic end generated code: output=3db4ed686179160d input=39d710ae3baaf1c7]*/ +{ + pid_t pgid = getpgid(pid); + if (pgid < 0) + return posix_error(); + return PyLong_FromPid(pgid); } -#endif +#endif /* HAVE_GETPGID */ -#ifdef HAVE_SYSCONF -static struct constdef posix_constants_sysconf[] = { -#ifdef _SC_2_CHAR_TERM - {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, -#endif -#ifdef _SC_2_C_BIND - {"SC_2_C_BIND", _SC_2_C_BIND}, -#endif -#ifdef _SC_2_C_DEV - {"SC_2_C_DEV", _SC_2_C_DEV}, -#endif -#ifdef _SC_2_C_VERSION - {"SC_2_C_VERSION", _SC_2_C_VERSION}, -#endif -#ifdef _SC_2_FORT_DEV - {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, -#endif -#ifdef _SC_2_FORT_RUN - {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, -#endif -#ifdef _SC_2_LOCALEDEF - {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, -#endif -#ifdef _SC_2_SW_DEV - {"SC_2_SW_DEV", _SC_2_SW_DEV}, -#endif -#ifdef _SC_2_UPE - {"SC_2_UPE", _SC_2_UPE}, -#endif -#ifdef _SC_2_VERSION - {"SC_2_VERSION", _SC_2_VERSION}, -#endif -#ifdef _SC_ABI_ASYNCHRONOUS_IO - {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, -#endif -#ifdef _SC_ACL - {"SC_ACL", _SC_ACL}, -#endif -#ifdef _SC_AIO_LISTIO_MAX - {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, -#endif -#ifdef _SC_AIO_MAX - {"SC_AIO_MAX", _SC_AIO_MAX}, -#endif -#ifdef _SC_AIO_PRIO_DELTA_MAX - {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, -#endif -#ifdef _SC_ARG_MAX - {"SC_ARG_MAX", _SC_ARG_MAX}, -#endif -#ifdef _SC_ASYNCHRONOUS_IO - {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, -#endif -#ifdef _SC_ATEXIT_MAX - {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, -#endif -#ifdef _SC_AUDIT - {"SC_AUDIT", _SC_AUDIT}, -#endif -#ifdef _SC_AVPHYS_PAGES - {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, -#endif -#ifdef _SC_BC_BASE_MAX - {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, -#endif -#ifdef _SC_BC_DIM_MAX - {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, -#endif -#ifdef _SC_BC_SCALE_MAX - {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, -#endif -#ifdef _SC_BC_STRING_MAX - {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, -#endif -#ifdef _SC_CAP - {"SC_CAP", _SC_CAP}, -#endif -#ifdef _SC_CHARCLASS_NAME_MAX - {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, -#endif -#ifdef _SC_CHAR_BIT - {"SC_CHAR_BIT", _SC_CHAR_BIT}, -#endif -#ifdef _SC_CHAR_MAX - {"SC_CHAR_MAX", _SC_CHAR_MAX}, -#endif -#ifdef _SC_CHAR_MIN - {"SC_CHAR_MIN", _SC_CHAR_MIN}, +#ifdef HAVE_GETPGRP +/*[clinic input] +os.getpgrp + +Return the current process group id. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_getpgrp__doc__, +"getpgrp($module, /)\n" +"--\n" +"\n" +"Return the current process group id."); + +#define OS_GETPGRP_METHODDEF \ + {"getpgrp", (PyCFunction)os_getpgrp, METH_NOARGS, os_getpgrp__doc__}, + +static PyObject * +os_getpgrp_impl(PyModuleDef *module); + +static PyObject * +os_getpgrp(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getpgrp_impl(module); +} + +static PyObject * +os_getpgrp_impl(PyModuleDef *module) +/*[clinic end generated code: output=3b0d3663ea054277 input=6846fb2bb9a3705e]*/ +{ +#ifdef GETPGRP_HAVE_ARG + return PyLong_FromPid(getpgrp(0)); +#else /* GETPGRP_HAVE_ARG */ + return PyLong_FromPid(getpgrp()); +#endif /* GETPGRP_HAVE_ARG */ +} +#endif /* HAVE_GETPGRP */ + + +#ifdef HAVE_SETPGRP +/*[clinic input] +os.setpgrp + +Make the current process the leader of its process group. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_setpgrp__doc__, +"setpgrp($module, /)\n" +"--\n" +"\n" +"Make the current process the leader of its process group."); + +#define OS_SETPGRP_METHODDEF \ + {"setpgrp", (PyCFunction)os_setpgrp, METH_NOARGS, os_setpgrp__doc__}, + +static PyObject * +os_setpgrp_impl(PyModuleDef *module); + +static PyObject * +os_setpgrp(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_setpgrp_impl(module); +} + +static PyObject * +os_setpgrp_impl(PyModuleDef *module) +/*[clinic end generated code: output=8fbb0ee29ef6fb2d input=1f0619fcb5731e7e]*/ +{ +#ifdef SETPGRP_HAVE_ARG + if (setpgrp(0, 0) < 0) +#else /* SETPGRP_HAVE_ARG */ + if (setpgrp() < 0) +#endif /* SETPGRP_HAVE_ARG */ + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_SETPGRP */ + +#ifdef HAVE_GETPPID + +#ifdef MS_WINDOWS +#include + +static PyObject* +win32_getppid() +{ + HANDLE snapshot; + pid_t mypid; + PyObject* result = NULL; + BOOL have_record; + PROCESSENTRY32 pe; + + mypid = getpid(); /* This function never fails */ + + snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (snapshot == INVALID_HANDLE_VALUE) + return PyErr_SetFromWindowsErr(GetLastError()); + + pe.dwSize = sizeof(pe); + have_record = Process32First(snapshot, &pe); + while (have_record) { + if (mypid == (pid_t)pe.th32ProcessID) { + /* We could cache the ulong value in a static variable. */ + result = PyLong_FromPid((pid_t)pe.th32ParentProcessID); + break; + } + + have_record = Process32Next(snapshot, &pe); + } + + /* If our loop exits and our pid was not found (result will be NULL) + * then GetLastError will return ERROR_NO_MORE_FILES. This is an + * error anyway, so let's raise it. */ + if (!result) + result = PyErr_SetFromWindowsErr(GetLastError()); + + CloseHandle(snapshot); + + return result; +} +#endif /*MS_WINDOWS*/ + + +/*[clinic input] +os.getppid + +Return the parent's process id. + +If the parent process has already exited, Windows machines will still +return its id; others systems will return the id of the 'init' process (1). +[clinic start generated code]*/ + +PyDoc_STRVAR(os_getppid__doc__, +"getppid($module, /)\n" +"--\n" +"\n" +"Return the parent\'s process id.\n" +"\n" +"If the parent process has already exited, Windows machines will still\n" +"return its id; others systems will return the id of the \'init\' process (1)."); + +#define OS_GETPPID_METHODDEF \ + {"getppid", (PyCFunction)os_getppid, METH_NOARGS, os_getppid__doc__}, + +static PyObject * +os_getppid_impl(PyModuleDef *module); + +static PyObject * +os_getppid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getppid_impl(module); +} + +static PyObject * +os_getppid_impl(PyModuleDef *module) +/*[clinic end generated code: output=9ff3b387781edf3a input=e637cb87539c030e]*/ +{ +#ifdef MS_WINDOWS + return win32_getppid(); +#else + return PyLong_FromPid(getppid()); #endif -#ifdef _SC_CHILD_MAX - {"SC_CHILD_MAX", _SC_CHILD_MAX}, +} +#endif /* HAVE_GETPPID */ + + +#ifdef HAVE_GETLOGIN +/*[clinic input] +os.getlogin + +Return the actual login name. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_getlogin__doc__, +"getlogin($module, /)\n" +"--\n" +"\n" +"Return the actual login name."); + +#define OS_GETLOGIN_METHODDEF \ + {"getlogin", (PyCFunction)os_getlogin, METH_NOARGS, os_getlogin__doc__}, + +static PyObject * +os_getlogin_impl(PyModuleDef *module); + +static PyObject * +os_getlogin(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getlogin_impl(module); +} + +static PyObject * +os_getlogin_impl(PyModuleDef *module) +/*[clinic end generated code: output=ab6211dab104cbb2 input=2a21ab1e917163df]*/ +{ + PyObject *result = NULL; +#ifdef MS_WINDOWS + wchar_t user_name[UNLEN + 1]; + DWORD num_chars = Py_ARRAY_LENGTH(user_name); + + if (GetUserNameW(user_name, &num_chars)) { + /* num_chars is the number of unicode chars plus null terminator */ + result = PyUnicode_FromWideChar(user_name, num_chars - 1); + } + else + result = PyErr_SetFromWindowsErr(GetLastError()); +#else + char *name; + int old_errno = errno; + + errno = 0; + name = getlogin(); + if (name == NULL) { + if (errno) + posix_error(); + else + PyErr_SetString(PyExc_OSError, "unable to determine login name"); + } + else + result = PyUnicode_DecodeFSDefault(name); + errno = old_errno; #endif -#ifdef _SC_CLK_TCK - {"SC_CLK_TCK", _SC_CLK_TCK}, -#endif -#ifdef _SC_COHER_BLKSZ - {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, -#endif -#ifdef _SC_COLL_WEIGHTS_MAX - {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, -#endif -#ifdef _SC_DCACHE_ASSOC - {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, -#endif -#ifdef _SC_DCACHE_BLKSZ - {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, -#endif -#ifdef _SC_DCACHE_LINESZ - {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, -#endif -#ifdef _SC_DCACHE_SZ - {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, -#endif -#ifdef _SC_DCACHE_TBLKSZ - {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, -#endif -#ifdef _SC_DELAYTIMER_MAX - {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, -#endif -#ifdef _SC_EQUIV_CLASS_MAX - {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, -#endif -#ifdef _SC_EXPR_NEST_MAX - {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, -#endif -#ifdef _SC_FSYNC - {"SC_FSYNC", _SC_FSYNC}, -#endif -#ifdef _SC_GETGR_R_SIZE_MAX - {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, -#endif -#ifdef _SC_GETPW_R_SIZE_MAX - {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, -#endif -#ifdef _SC_ICACHE_ASSOC - {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, -#endif -#ifdef _SC_ICACHE_BLKSZ - {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, -#endif -#ifdef _SC_ICACHE_LINESZ - {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, -#endif -#ifdef _SC_ICACHE_SZ - {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, -#endif -#ifdef _SC_INF - {"SC_INF", _SC_INF}, -#endif -#ifdef _SC_INT_MAX - {"SC_INT_MAX", _SC_INT_MAX}, -#endif -#ifdef _SC_INT_MIN - {"SC_INT_MIN", _SC_INT_MIN}, -#endif -#ifdef _SC_IOV_MAX - {"SC_IOV_MAX", _SC_IOV_MAX}, -#endif -#ifdef _SC_IP_SECOPTS - {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, -#endif -#ifdef _SC_JOB_CONTROL - {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, -#endif -#ifdef _SC_KERN_POINTERS - {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, -#endif -#ifdef _SC_KERN_SIM - {"SC_KERN_SIM", _SC_KERN_SIM}, -#endif -#ifdef _SC_LINE_MAX - {"SC_LINE_MAX", _SC_LINE_MAX}, -#endif -#ifdef _SC_LOGIN_NAME_MAX - {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, -#endif -#ifdef _SC_LOGNAME_MAX - {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, -#endif -#ifdef _SC_LONG_BIT - {"SC_LONG_BIT", _SC_LONG_BIT}, -#endif -#ifdef _SC_MAC - {"SC_MAC", _SC_MAC}, -#endif -#ifdef _SC_MAPPED_FILES - {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, -#endif -#ifdef _SC_MAXPID - {"SC_MAXPID", _SC_MAXPID}, -#endif -#ifdef _SC_MB_LEN_MAX - {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, -#endif -#ifdef _SC_MEMLOCK - {"SC_MEMLOCK", _SC_MEMLOCK}, -#endif -#ifdef _SC_MEMLOCK_RANGE - {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, -#endif -#ifdef _SC_MEMORY_PROTECTION - {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION}, -#endif -#ifdef _SC_MESSAGE_PASSING - {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING}, -#endif -#ifdef _SC_MMAP_FIXED_ALIGNMENT - {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, -#endif -#ifdef _SC_MQ_OPEN_MAX - {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX}, + return result; +} +#endif /* HAVE_GETLOGIN */ + + +#ifdef HAVE_GETUID +/*[clinic input] +os.getuid + +Return the current process's user id. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_getuid__doc__, +"getuid($module, /)\n" +"--\n" +"\n" +"Return the current process\'s user id."); + +#define OS_GETUID_METHODDEF \ + {"getuid", (PyCFunction)os_getuid, METH_NOARGS, os_getuid__doc__}, + +static PyObject * +os_getuid_impl(PyModuleDef *module); + +static PyObject * +os_getuid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_getuid_impl(module); +} + +static PyObject * +os_getuid_impl(PyModuleDef *module) +/*[clinic end generated code: output=77e0dcf2e37d1e89 input=b53c8b35f110a516]*/ +{ + return _PyLong_FromUid(getuid()); +} +#endif /* HAVE_GETUID */ + + +#ifdef MS_WINDOWS +#define HAVE_KILL +#endif /* MS_WINDOWS */ + +#ifdef HAVE_KILL +/*[clinic input] +os.kill + + pid: pid_t + signal: Py_ssize_t + / + +Kill a process with a signal. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_kill__doc__, +"kill($module, pid, signal, /)\n" +"--\n" +"\n" +"Kill a process with a signal."); + +#define OS_KILL_METHODDEF \ + {"kill", (PyCFunction)os_kill, METH_VARARGS, os_kill__doc__}, + +static PyObject * +os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal); + +static PyObject * +os_kill(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + pid_t pid; + Py_ssize_t signal; + + if (!PyArg_ParseTuple(args, + "" _Py_PARSE_PID "n:kill", + &pid, &signal)) + goto exit; + return_value = os_kill_impl(module, pid, signal); + +exit: + return return_value; +} + +static PyObject * +os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal) +/*[clinic end generated code: output=2f5c77920ed575e6 input=61a36b86ca275ab9]*/ +#ifndef MS_WINDOWS +{ + if (kill(pid, (int)signal) == -1) + return posix_error(); + Py_RETURN_NONE; +} +#else /* !MS_WINDOWS */ +{ + PyObject *result; + DWORD sig = (DWORD)signal; + DWORD err; + HANDLE handle; + + /* Console processes which share a common console can be sent CTRL+C or + CTRL+BREAK events, provided they handle said events. */ + if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) { + if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) { + err = GetLastError(); + PyErr_SetFromWindowsErr(err); + } + else + Py_RETURN_NONE; + } + + /* If the signal is outside of what GenerateConsoleCtrlEvent can use, + attempt to open and terminate the process. */ + handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid); + if (handle == NULL) { + err = GetLastError(); + return PyErr_SetFromWindowsErr(err); + } + + if (TerminateProcess(handle, sig) == 0) { + err = GetLastError(); + result = PyErr_SetFromWindowsErr(err); + } else { + Py_INCREF(Py_None); + result = Py_None; + } + + CloseHandle(handle); + return result; +} +#endif /* !MS_WINDOWS */ +#endif /* HAVE_KILL */ + + +#ifdef HAVE_KILLPG +/*[clinic input] +os.killpg + + pgid: pid_t + signal: int + / + +Kill a process group with a signal. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_killpg__doc__, +"killpg($module, pgid, signal, /)\n" +"--\n" +"\n" +"Kill a process group with a signal."); + +#define OS_KILLPG_METHODDEF \ + {"killpg", (PyCFunction)os_killpg, METH_VARARGS, os_killpg__doc__}, + +static PyObject * +os_killpg_impl(PyModuleDef *module, pid_t pgid, int signal); + +static PyObject * +os_killpg(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + pid_t pgid; + int signal; + + if (!PyArg_ParseTuple(args, + "" _Py_PARSE_PID "i:killpg", + &pgid, &signal)) + goto exit; + return_value = os_killpg_impl(module, pgid, signal); + +exit: + return return_value; +} + +static PyObject * +os_killpg_impl(PyModuleDef *module, pid_t pgid, int signal) +/*[clinic end generated code: output=0e05215d1c007e01 input=38b5449eb8faec19]*/ +{ + /* XXX some man pages make the `pgid` parameter an int, others + a pid_t. Since getpgrp() returns a pid_t, we assume killpg should + take the same type. Moreover, pid_t is always at least as wide as + int (else compilation of this module fails), which is safe. */ + if (killpg(pgid, signal) == -1) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_KILLPG */ + + +#ifdef HAVE_PLOCK +#ifdef HAVE_SYS_LOCK_H +#include +#endif + +/*[clinic input] +os.plock + op: int + / + +Lock program segments into memory."); +[clinic start generated code]*/ + +PyDoc_STRVAR(os_plock__doc__, +"plock($module, op, /)\n" +"--\n" +"\n" +"Lock program segments into memory.\");"); + +#define OS_PLOCK_METHODDEF \ + {"plock", (PyCFunction)os_plock, METH_VARARGS, os_plock__doc__}, + +static PyObject * +os_plock_impl(PyModuleDef *module, int op); + +static PyObject * +os_plock(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int op; + + if (!PyArg_ParseTuple(args, + "i:plock", + &op)) + goto exit; + return_value = os_plock_impl(module, op); + +exit: + return return_value; +} + +static PyObject * +os_plock_impl(PyModuleDef *module, int op) +/*[clinic end generated code: output=2744fe4b6e5f4dbc input=e6e5e348e1525f60]*/ +{ + if (plock(op) == -1) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_PLOCK */ + + +#ifdef HAVE_SETUID +/*[clinic input] +os.setuid + + uid: uid_t + / + +Set the current process's user id. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_setuid__doc__, +"setuid($module, uid, /)\n" +"--\n" +"\n" +"Set the current process\'s user id."); + +#define OS_SETUID_METHODDEF \ + {"setuid", (PyCFunction)os_setuid, METH_VARARGS, os_setuid__doc__}, + +static PyObject * +os_setuid_impl(PyModuleDef *module, uid_t uid); + +static PyObject * +os_setuid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + uid_t uid; + + if (!PyArg_ParseTuple(args, + "O&:setuid", + _Py_Uid_Converter, &uid)) + goto exit; + return_value = os_setuid_impl(module, uid); + +exit: + return return_value; +} + +static PyObject * +os_setuid_impl(PyModuleDef *module, uid_t uid) +/*[clinic end generated code: output=aea344bc22ccf400 input=c921a3285aa22256]*/ +{ + if (setuid(uid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETUID */ + + +#ifdef HAVE_SETEUID +/*[clinic input] +os.seteuid + + euid: uid_t + / + +Set the current process's effective user id. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_seteuid__doc__, +"seteuid($module, euid, /)\n" +"--\n" +"\n" +"Set the current process\'s effective user id."); + +#define OS_SETEUID_METHODDEF \ + {"seteuid", (PyCFunction)os_seteuid, METH_VARARGS, os_seteuid__doc__}, + +static PyObject * +os_seteuid_impl(PyModuleDef *module, uid_t euid); + +static PyObject * +os_seteuid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + uid_t euid; + + if (!PyArg_ParseTuple(args, + "O&:seteuid", + _Py_Uid_Converter, &euid)) + goto exit; + return_value = os_seteuid_impl(module, euid); + +exit: + return return_value; +} + +static PyObject * +os_seteuid_impl(PyModuleDef *module, uid_t euid) +/*[clinic end generated code: output=6e824cce4f3b8a5d input=ba93d927e4781aa9]*/ +{ + if (seteuid(euid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETEUID */ + + +#ifdef HAVE_SETEGID +/*[clinic input] +os.setegid + + egid: gid_t + / + +Set the current process's effective group id. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_setegid__doc__, +"setegid($module, egid, /)\n" +"--\n" +"\n" +"Set the current process\'s effective group id."); + +#define OS_SETEGID_METHODDEF \ + {"setegid", (PyCFunction)os_setegid, METH_VARARGS, os_setegid__doc__}, + +static PyObject * +os_setegid_impl(PyModuleDef *module, gid_t egid); + +static PyObject * +os_setegid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + gid_t egid; + + if (!PyArg_ParseTuple(args, + "O&:setegid", + _Py_Gid_Converter, &egid)) + goto exit; + return_value = os_setegid_impl(module, egid); + +exit: + return return_value; +} + +static PyObject * +os_setegid_impl(PyModuleDef *module, gid_t egid) +/*[clinic end generated code: output=80a32263a4d56a9c input=4080526d0ccd6ce3]*/ +{ + if (setegid(egid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETEGID */ + + +#ifdef HAVE_SETREUID +/*[clinic input] +os.setreuid + + ruid: uid_t + euid: uid_t + / + +Set the current process's real and effective user ids. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_setreuid__doc__, +"setreuid($module, ruid, euid, /)\n" +"--\n" +"\n" +"Set the current process\'s real and effective user ids."); + +#define OS_SETREUID_METHODDEF \ + {"setreuid", (PyCFunction)os_setreuid, METH_VARARGS, os_setreuid__doc__}, + +static PyObject * +os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid); + +static PyObject * +os_setreuid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + uid_t ruid; + uid_t euid; + + if (!PyArg_ParseTuple(args, + "O&O&:setreuid", + _Py_Uid_Converter, &ruid, _Py_Uid_Converter, &euid)) + goto exit; + return_value = os_setreuid_impl(module, ruid, euid); + +exit: + return return_value; +} + +static PyObject * +os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid) +/*[clinic end generated code: output=d7f226f943dad739 input=0ca8978de663880c]*/ +{ + if (setreuid(ruid, euid) < 0) { + return posix_error(); + } else { + Py_INCREF(Py_None); + return Py_None; + } +} +#endif /* HAVE_SETREUID */ + + +#ifdef HAVE_SETREGID +/*[clinic input] +os.setregid + + rgid: gid_t + egid: gid_t + / + +Set the current process's real and effective group ids. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_setregid__doc__, +"setregid($module, rgid, egid, /)\n" +"--\n" +"\n" +"Set the current process\'s real and effective group ids."); + +#define OS_SETREGID_METHODDEF \ + {"setregid", (PyCFunction)os_setregid, METH_VARARGS, os_setregid__doc__}, + +static PyObject * +os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid); + +static PyObject * +os_setregid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + gid_t rgid; + gid_t egid; + + if (!PyArg_ParseTuple(args, + "O&O&:setregid", + _Py_Gid_Converter, &rgid, _Py_Gid_Converter, &egid)) + goto exit; + return_value = os_setregid_impl(module, rgid, egid); + +exit: + return return_value; +} + +static PyObject * +os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid) +/*[clinic end generated code: output=a82d9ab70f8e6562 input=c59499f72846db78]*/ +{ + if (setregid(rgid, egid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETREGID */ + + +#ifdef HAVE_SETGID +/*[clinic input] +os.setgid + gid: gid_t + / + +Set the current process's group id. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_setgid__doc__, +"setgid($module, gid, /)\n" +"--\n" +"\n" +"Set the current process\'s group id."); + +#define OS_SETGID_METHODDEF \ + {"setgid", (PyCFunction)os_setgid, METH_VARARGS, os_setgid__doc__}, + +static PyObject * +os_setgid_impl(PyModuleDef *module, gid_t gid); + +static PyObject * +os_setgid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + gid_t gid; + + if (!PyArg_ParseTuple(args, + "O&:setgid", + _Py_Gid_Converter, &gid)) + goto exit; + return_value = os_setgid_impl(module, gid); + +exit: + return return_value; +} + +static PyObject * +os_setgid_impl(PyModuleDef *module, gid_t gid) +/*[clinic end generated code: output=08287886db435f23 input=27d30c4059045dc6]*/ +{ + if (setgid(gid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETGID */ + + +#ifdef HAVE_SETGROUPS +/*[clinic input] +os.setgroups + + groups: object + / + +Set the groups of the current process to list. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_setgroups__doc__, +"setgroups($module, groups, /)\n" +"--\n" +"\n" +"Set the groups of the current process to list."); + +#define OS_SETGROUPS_METHODDEF \ + {"setgroups", (PyCFunction)os_setgroups, METH_O, os_setgroups__doc__}, + +static PyObject * +os_setgroups(PyModuleDef *module, PyObject *groups) +/*[clinic end generated code: output=0b8de65d5b3cda94 input=fa742ca3daf85a7e]*/ +{ + int i, len; + gid_t grouplist[MAX_GROUPS]; + + if (!PySequence_Check(groups)) { + PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); + return NULL; + } + len = PySequence_Size(groups); + if (len > MAX_GROUPS) { + PyErr_SetString(PyExc_ValueError, "too many groups"); + return NULL; + } + for(i = 0; i < len; i++) { + PyObject *elem; + elem = PySequence_GetItem(groups, i); + if (!elem) + return NULL; + if (!PyLong_Check(elem)) { + PyErr_SetString(PyExc_TypeError, + "groups must be integers"); + Py_DECREF(elem); + return NULL; + } else { + if (!_Py_Gid_Converter(elem, &grouplist[i])) { + Py_DECREF(elem); + return NULL; + } + } + Py_DECREF(elem); + } + + if (setgroups(len, grouplist) < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} +#endif /* HAVE_SETGROUPS */ + +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) +static PyObject * +wait_helper(pid_t pid, int status, struct rusage *ru) +{ + PyObject *result; + static PyObject *struct_rusage; + _Py_IDENTIFIER(struct_rusage); + + if (pid == -1) + return posix_error(); + + if (struct_rusage == NULL) { + PyObject *m = PyImport_ImportModuleNoBlock("resource"); + if (m == NULL) + return NULL; + struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage); + Py_DECREF(m); + if (struct_rusage == NULL) + return NULL; + } + + /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ + result = PyStructSequence_New((PyTypeObject*) struct_rusage); + if (!result) + return NULL; + +#ifndef doubletime +#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) +#endif + + PyStructSequence_SET_ITEM(result, 0, + PyFloat_FromDouble(doubletime(ru->ru_utime))); + PyStructSequence_SET_ITEM(result, 1, + PyFloat_FromDouble(doubletime(ru->ru_stime))); +#define SET_INT(result, index, value)\ + PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value)) + SET_INT(result, 2, ru->ru_maxrss); + SET_INT(result, 3, ru->ru_ixrss); + SET_INT(result, 4, ru->ru_idrss); + SET_INT(result, 5, ru->ru_isrss); + SET_INT(result, 6, ru->ru_minflt); + SET_INT(result, 7, ru->ru_majflt); + SET_INT(result, 8, ru->ru_nswap); + SET_INT(result, 9, ru->ru_inblock); + SET_INT(result, 10, ru->ru_oublock); + SET_INT(result, 11, ru->ru_msgsnd); + SET_INT(result, 12, ru->ru_msgrcv); + SET_INT(result, 13, ru->ru_nsignals); + SET_INT(result, 14, ru->ru_nvcsw); + SET_INT(result, 15, ru->ru_nivcsw); +#undef SET_INT + + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + + return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result); +} +#endif /* HAVE_WAIT3 || HAVE_WAIT4 */ + + +#ifdef HAVE_WAIT3 +/*[clinic input] +os.wait3 + + options: int +Wait for completion of a child process. + +Returns a tuple of information about the child process: + (pid, status, rusage) +[clinic start generated code]*/ + +PyDoc_STRVAR(os_wait3__doc__, +"wait3($module, /, options)\n" +"--\n" +"\n" +"Wait for completion of a child process.\n" +"\n" +"Returns a tuple of information about the child process:\n" +" (pid, status, rusage)"); + +#define OS_WAIT3_METHODDEF \ + {"wait3", (PyCFunction)os_wait3, METH_VARARGS|METH_KEYWORDS, os_wait3__doc__}, + +static PyObject * +os_wait3_impl(PyModuleDef *module, int options); + +static PyObject * +os_wait3(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"options", NULL}; + int options; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:wait3", _keywords, + &options)) + goto exit; + return_value = os_wait3_impl(module, options); + +exit: + return return_value; +} + +static PyObject * +os_wait3_impl(PyModuleDef *module, int options) +/*[clinic end generated code: output=1f2a63b6a93cbb57 input=8ac4c56956b61710]*/ +{ + pid_t pid; + struct rusage ru; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + pid = wait3(&status, options, &ru); + Py_END_ALLOW_THREADS + } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (pid < 0) + return (!async_err) ? posix_error() : NULL; + + return wait_helper(pid, WAIT_STATUS_INT(status), &ru); +} +#endif /* HAVE_WAIT3 */ + + +#ifdef HAVE_WAIT4 +/*[clinic input] + +os.wait4 + + pid: pid_t + options: int + +Wait for completion of a specific child process. + +Returns a tuple of information about the child process: + (pid, status, rusage) +[clinic start generated code]*/ + +PyDoc_STRVAR(os_wait4__doc__, +"wait4($module, /, pid, options)\n" +"--\n" +"\n" +"Wait for completion of a specific child process.\n" +"\n" +"Returns a tuple of information about the child process:\n" +" (pid, status, rusage)"); + +#define OS_WAIT4_METHODDEF \ + {"wait4", (PyCFunction)os_wait4, METH_VARARGS|METH_KEYWORDS, os_wait4__doc__}, + +static PyObject * +os_wait4_impl(PyModuleDef *module, pid_t pid, int options); + +static PyObject * +os_wait4(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"pid", "options", NULL}; + pid_t pid; + int options; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "" _Py_PARSE_PID "i:wait4", _keywords, + &pid, &options)) + goto exit; + return_value = os_wait4_impl(module, pid, options); + +exit: + return return_value; +} + +static PyObject * +os_wait4_impl(PyModuleDef *module, pid_t pid, int options) +/*[clinic end generated code: output=20dfb05289d37dc6 input=d11deed0750600ba]*/ +{ + pid_t res; + struct rusage ru; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = wait4(pid, &status, options, &ru); + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + return wait_helper(res, WAIT_STATUS_INT(status), &ru); +} +#endif /* HAVE_WAIT4 */ + + +#if defined(HAVE_WAITID) && !defined(__APPLE__) +/*[clinic input] +os.waitid + + idtype: idtype_t + Must be one of be P_PID, P_PGID or P_ALL. + id: id_t + The id to wait on. + options: int + Constructed from the ORing of one or more of WEXITED, WSTOPPED + or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT. + / + +Returns the result of waiting for a process or processes. + +Returns either waitid_result or None if WNOHANG is specified and there are +no children in a waitable state. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_waitid__doc__, +"waitid($module, idtype, id, options, /)\n" +"--\n" +"\n" +"Returns the result of waiting for a process or processes.\n" +"\n" +" idtype\n" +" Must be one of be P_PID, P_PGID or P_ALL.\n" +" id\n" +" The id to wait on.\n" +" options\n" +" Constructed from the ORing of one or more of WEXITED, WSTOPPED\n" +" or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n" +"\n" +"Returns either waitid_result or None if WNOHANG is specified and there are\n" +"no children in a waitable state."); + +#define OS_WAITID_METHODDEF \ + {"waitid", (PyCFunction)os_waitid, METH_VARARGS, os_waitid__doc__}, + +static PyObject * +os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options); + +static PyObject * +os_waitid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + idtype_t idtype; + id_t id; + int options; + + if (!PyArg_ParseTuple(args, + "i" _Py_PARSE_PID "i:waitid", + &idtype, &id, &options)) + goto exit; + return_value = os_waitid_impl(module, idtype, id, options); + +exit: + return return_value; +} + +static PyObject * +os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options) +/*[clinic end generated code: output=fb44bf97f01021b2 input=d8e7f76e052b7920]*/ +{ + PyObject *result; + int res; + int async_err = 0; + siginfo_t si; + si.si_pid = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = waitid(idtype, id, &si, options); + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + if (si.si_pid == 0) + Py_RETURN_NONE; + + result = PyStructSequence_New(&WaitidResultType); + if (!result) + return NULL; + + PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid)); + PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid)); + PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo))); + PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status))); + PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code))); + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + + return result; +} +#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */ + + +#if defined(HAVE_WAITPID) +/*[clinic input] +os.waitpid + pid: pid_t + options: int + / + +Wait for completion of a given child process. + +Returns a tuple of information regarding the child process: + (pid, status) + +The options argument is ignored on Windows. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_waitpid__doc__, +"waitpid($module, pid, options, /)\n" +"--\n" +"\n" +"Wait for completion of a given child process.\n" +"\n" +"Returns a tuple of information regarding the child process:\n" +" (pid, status)\n" +"\n" +"The options argument is ignored on Windows."); + +#define OS_WAITPID_METHODDEF \ + {"waitpid", (PyCFunction)os_waitpid, METH_VARARGS, os_waitpid__doc__}, + +static PyObject * +os_waitpid_impl(PyModuleDef *module, pid_t pid, int options); + +static PyObject * +os_waitpid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + pid_t pid; + int options; + + if (!PyArg_ParseTuple(args, + "" _Py_PARSE_PID "i:waitpid", + &pid, &options)) + goto exit; + return_value = os_waitpid_impl(module, pid, options); + +exit: + return return_value; +} + +static PyObject * +os_waitpid_impl(PyModuleDef *module, pid_t pid, int options) +/*[clinic end generated code: output=095a6b00af70b7ac input=0bf1666b8758fda3]*/ +{ + pid_t res; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = waitpid(pid, &status, options); + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res < 0) + return (!async_err) ? posix_error() : NULL; + + return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status)); +} +#elif defined(HAVE_CWAIT) +/* MS C has a variant of waitpid() that's usable for most purposes. */ +/*[clinic input] +os.waitpid + pid: Py_intptr_t + options: int + / + +Wait for completion of a given process. + +Returns a tuple of information regarding the process: + (pid, status << 8) + +The options argument is ignored on Windows. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_waitpid__doc__, +"waitpid($module, pid, options, /)\n" +"--\n" +"\n" +"Wait for completion of a given process.\n" +"\n" +"Returns a tuple of information regarding the process:\n" +" (pid, status << 8)\n" +"\n" +"The options argument is ignored on Windows."); + +#define OS_WAITPID_METHODDEF \ + {"waitpid", (PyCFunction)os_waitpid, METH_VARARGS, os_waitpid__doc__}, + +static PyObject * +os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options); + +static PyObject * +os_waitpid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_intptr_t pid; + int options; + + if (!PyArg_ParseTuple(args, + "" _Py_PARSE_INTPTR "i:waitpid", + &pid, &options)) + goto exit; + return_value = os_waitpid_impl(module, pid, options); + +exit: + return return_value; +} + +static PyObject * +os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options) +/*[clinic end generated code: output=c20b95b15ad44a3a input=444c8f51cca5b862]*/ +{ + int status; + Py_intptr_t res; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = _cwait(&status, pid, options); + Py_END_ALLOW_THREADS + } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res != 0) + return (!async_err) ? posix_error() : NULL; + + /* shift the status left a byte so this is more like the POSIX waitpid */ + return Py_BuildValue(_Py_PARSE_INTPTR "i", res, status << 8); +} +#endif + + +#ifdef HAVE_WAIT +/*[clinic input] +os.wait + +Wait for completion of a child process. + +Returns a tuple of information about the child process: + (pid, status) +[clinic start generated code]*/ + +PyDoc_STRVAR(os_wait__doc__, +"wait($module, /)\n" +"--\n" +"\n" +"Wait for completion of a child process.\n" +"\n" +"Returns a tuple of information about the child process:\n" +" (pid, status)"); + +#define OS_WAIT_METHODDEF \ + {"wait", (PyCFunction)os_wait, METH_NOARGS, os_wait__doc__}, + +static PyObject * +os_wait_impl(PyModuleDef *module); + +static PyObject * +os_wait(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_wait_impl(module); +} + +static PyObject * +os_wait_impl(PyModuleDef *module) +/*[clinic end generated code: output=2a83a9d164e7e6a8 input=03b0182d4a4700ce]*/ +{ + pid_t pid; + int async_err = 0; + WAIT_TYPE status; + WAIT_STATUS_INT(status) = 0; + + do { + Py_BEGIN_ALLOW_THREADS + pid = wait(&status); + Py_END_ALLOW_THREADS + } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (pid < 0) + return (!async_err) ? posix_error() : NULL; + + return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); +} +#endif /* HAVE_WAIT */ + + +#if defined(HAVE_READLINK) || defined(MS_WINDOWS) +PyDoc_STRVAR(readlink__doc__, +"readlink(path, *, dir_fd=None) -> path\n\n\ +Return a string representing the path to which the symbolic link points.\n\ +\n\ +If dir_fd is not None, it should be a file descriptor open to a directory,\n\ + and path should be relative; path will then be relative to that directory.\n\ +dir_fd may not be implemented on your platform.\n\ + If it is unavailable, using it will raise a NotImplementedError."); +#endif + +#ifdef HAVE_READLINK + +/* AC 3.5: merge win32 and not together */ +static PyObject * +posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) +{ + path_t path; + int dir_fd = DEFAULT_DIR_FD; + char buffer[MAXPATHLEN]; + ssize_t length; + PyObject *return_value = NULL; + static char *keywords[] = {"path", "dir_fd", NULL}; + + memset(&path, 0, sizeof(path)); + path.function_name = "readlink"; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords, + path_converter, &path, + READLINKAT_DIR_FD_CONVERTER, &dir_fd)) + return NULL; + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_READLINKAT + if (dir_fd != DEFAULT_DIR_FD) + length = readlinkat(dir_fd, path.narrow, buffer, sizeof(buffer)); + else +#endif + length = readlink(path.narrow, buffer, sizeof(buffer)); + Py_END_ALLOW_THREADS + + if (length < 0) { + return_value = path_error(&path); + goto exit; + } + + if (PyUnicode_Check(path.object)) + return_value = PyUnicode_DecodeFSDefaultAndSize(buffer, length); + else + return_value = PyBytes_FromStringAndSize(buffer, length); +exit: + path_cleanup(&path); + return return_value; +} + +#endif /* HAVE_READLINK */ + +#if !defined(HAVE_READLINK) && defined(MS_WINDOWS) + +static PyObject * +win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) +{ + wchar_t *path; + DWORD n_bytes_returned; + DWORD io_result; + PyObject *po, *result; + int dir_fd; + HANDLE reparse_point_handle; + + char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer; + wchar_t *print_name; + + static char *keywords[] = {"path", "dir_fd", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords, + &po, + dir_fd_unavailable, &dir_fd + )) + return NULL; + + path = PyUnicode_AsUnicode(po); + if (path == NULL) + return NULL; + + /* First get a handle to the reparse point */ + Py_BEGIN_ALLOW_THREADS + reparse_point_handle = CreateFileW( + path, + 0, + 0, + 0, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, + 0); + Py_END_ALLOW_THREADS + + if (reparse_point_handle==INVALID_HANDLE_VALUE) + return win32_error_object("readlink", po); + + Py_BEGIN_ALLOW_THREADS + /* New call DeviceIoControl to read the reparse point */ + io_result = DeviceIoControl( + reparse_point_handle, + FSCTL_GET_REPARSE_POINT, + 0, 0, /* in buffer */ + target_buffer, sizeof(target_buffer), + &n_bytes_returned, + 0 /* we're not using OVERLAPPED_IO */ + ); + CloseHandle(reparse_point_handle); + Py_END_ALLOW_THREADS + + if (io_result==0) + return win32_error_object("readlink", po); + + if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) + { + PyErr_SetString(PyExc_ValueError, + "not a symbolic link"); + return NULL; + } + print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer + + rdb->SymbolicLinkReparseBuffer.PrintNameOffset; + + result = PyUnicode_FromWideChar(print_name, + rdb->SymbolicLinkReparseBuffer.PrintNameLength/2); + return result; +} + +#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */ + + + +#ifdef HAVE_SYMLINK + +#if defined(MS_WINDOWS) + +/* Grab CreateSymbolicLinkW dynamically from kernel32 */ +static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD) = NULL; +static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPSTR, LPSTR, DWORD) = NULL; + +static int +check_CreateSymbolicLink(void) +{ + HINSTANCE hKernel32; + /* only recheck */ + if (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA) + return 1; + hKernel32 = GetModuleHandleW(L"KERNEL32"); + *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32, + "CreateSymbolicLinkW"); + *(FARPROC*)&Py_CreateSymbolicLinkA = GetProcAddress(hKernel32, + "CreateSymbolicLinkA"); + return (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA); +} + +/* Remove the last portion of the path */ +static void +_dirnameW(WCHAR *path) +{ + WCHAR *ptr; + + /* walk the path from the end until a backslash is encountered */ + for(ptr = path + wcslen(path); ptr != path; ptr--) { + if (*ptr == L'\\' || *ptr == L'/') + break; + } + *ptr = 0; +} + +/* Remove the last portion of the path */ +static void +_dirnameA(char *path) +{ + char *ptr; + + /* walk the path from the end until a backslash is encountered */ + for(ptr = path + strlen(path); ptr != path; ptr--) { + if (*ptr == '\\' || *ptr == '/') + break; + } + *ptr = 0; +} + +/* Is this path absolute? */ +static int +_is_absW(const WCHAR *path) +{ + return path[0] == L'\\' || path[0] == L'/' || path[1] == L':'; + +} + +/* Is this path absolute? */ +static int +_is_absA(const char *path) +{ + return path[0] == '\\' || path[0] == '/' || path[1] == ':'; + +} + +/* join root and rest with a backslash */ +static void +_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) +{ + size_t root_len; + + if (_is_absW(rest)) { + wcscpy(dest_path, rest); + return; + } + + root_len = wcslen(root); + + wcscpy(dest_path, root); + if(root_len) { + dest_path[root_len] = L'\\'; + root_len++; + } + wcscpy(dest_path+root_len, rest); +} + +/* join root and rest with a backslash */ +static void +_joinA(char *dest_path, const char *root, const char *rest) +{ + size_t root_len; + + if (_is_absA(rest)) { + strcpy(dest_path, rest); + return; + } + + root_len = strlen(root); + + strcpy(dest_path, root); + if(root_len) { + dest_path[root_len] = '\\'; + root_len++; + } + strcpy(dest_path+root_len, rest); +} + +/* Return True if the path at src relative to dest is a directory */ +static int +_check_dirW(WCHAR *src, WCHAR *dest) +{ + WIN32_FILE_ATTRIBUTE_DATA src_info; + WCHAR dest_parent[MAX_PATH]; + WCHAR src_resolved[MAX_PATH] = L""; + + /* dest_parent = os.path.dirname(dest) */ + wcscpy(dest_parent, dest); + _dirnameW(dest_parent); + /* src_resolved = os.path.join(dest_parent, src) */ + _joinW(src_resolved, dest_parent, src); + return ( + GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) + && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY + ); +} + +/* Return True if the path at src relative to dest is a directory */ +static int +_check_dirA(char *src, char *dest) +{ + WIN32_FILE_ATTRIBUTE_DATA src_info; + char dest_parent[MAX_PATH]; + char src_resolved[MAX_PATH] = ""; + + /* dest_parent = os.path.dirname(dest) */ + strcpy(dest_parent, dest); + _dirnameA(dest_parent); + /* src_resolved = os.path.join(dest_parent, src) */ + _joinA(src_resolved, dest_parent, src); + return ( + GetFileAttributesExA(src_resolved, GetFileExInfoStandard, &src_info) + && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY + ); +} +#endif + + +/*[clinic input] +os.symlink + src: path_t + dst: path_t + target_is_directory: bool = False + * + dir_fd: dir_fd(requires='symlinkat')=None + +# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\ + +Create a symbolic link pointing to src named dst. + +target_is_directory is required on Windows if the target is to be + interpreted as a directory. (On Windows, symlink requires + Windows 6.0 or greater, and raises a NotImplementedError otherwise.) + target_is_directory is ignored on non-Windows platforms. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. + +[clinic start generated code]*/ + +PyDoc_STRVAR(os_symlink__doc__, +"symlink($module, /, src, dst, target_is_directory=False, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a symbolic link pointing to src named dst.\n" +"\n" +"target_is_directory is required on Windows if the target is to be\n" +" interpreted as a directory. (On Windows, symlink requires\n" +" Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n" +" target_is_directory is ignored on non-Windows platforms.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_SYMLINK_METHODDEF \ + {"symlink", (PyCFunction)os_symlink, METH_VARARGS|METH_KEYWORDS, os_symlink__doc__}, + +static PyObject * +os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd); + +static PyObject * +os_symlink(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL}; + path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0); + path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0); + int target_is_directory = 0; + int dir_fd = DEFAULT_DIR_FD; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&O&|p$O&:symlink", _keywords, + path_converter, &src, path_converter, &dst, &target_is_directory, SYMLINKAT_DIR_FD_CONVERTER, &dir_fd)) + goto exit; + return_value = os_symlink_impl(module, &src, &dst, target_is_directory, dir_fd); + +exit: + /* Cleanup for src */ + path_cleanup(&src); + /* Cleanup for dst */ + path_cleanup(&dst); + + return return_value; +} + +static PyObject * +os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd) +/*[clinic end generated code: output=1a31e6d88aafe9b6 input=e820ec4472547bc3]*/ +{ +#ifdef MS_WINDOWS + DWORD result; +#else + int result; +#endif + +#ifdef MS_WINDOWS + if (!check_CreateSymbolicLink()) { + PyErr_SetString(PyExc_NotImplementedError, + "CreateSymbolicLink functions not found"); + return NULL; + } + if (!win32_can_symlink) { + PyErr_SetString(PyExc_OSError, "symbolic link privilege not held"); + return NULL; + } +#endif + + if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { + PyErr_SetString(PyExc_ValueError, + "symlink: src and dst must be the same type"); + return NULL; + } + +#ifdef MS_WINDOWS + + Py_BEGIN_ALLOW_THREADS + if (dst->wide) { + /* if src is a directory, ensure target_is_directory==1 */ + target_is_directory |= _check_dirW(src->wide, dst->wide); + result = Py_CreateSymbolicLinkW(dst->wide, src->wide, + target_is_directory); + } + else { + /* if src is a directory, ensure target_is_directory==1 */ + target_is_directory |= _check_dirA(src->narrow, dst->narrow); + result = Py_CreateSymbolicLinkA(dst->narrow, src->narrow, + target_is_directory); + } + Py_END_ALLOW_THREADS + + if (!result) + return path_error2(src, dst); + +#else + + Py_BEGIN_ALLOW_THREADS +#if HAVE_SYMLINKAT + if (dir_fd != DEFAULT_DIR_FD) + result = symlinkat(src->narrow, dir_fd, dst->narrow); + else +#endif + result = symlink(src->narrow, dst->narrow); + Py_END_ALLOW_THREADS + + if (result) + return path_error2(src, dst); +#endif + + Py_RETURN_NONE; +} +#endif /* HAVE_SYMLINK */ + + + + +static PyStructSequence_Field times_result_fields[] = { + {"user", "user time"}, + {"system", "system time"}, + {"children_user", "user time of children"}, + {"children_system", "system time of children"}, + {"elapsed", "elapsed time since an arbitrary point in the past"}, + {NULL} +}; + +PyDoc_STRVAR(times_result__doc__, +"times_result: Result from os.times().\n\n\ +This object may be accessed either as a tuple of\n\ + (user, system, children_user, children_system, elapsed),\n\ +or via the attributes user, system, children_user, children_system,\n\ +and elapsed.\n\ +\n\ +See os.times for more information."); + +static PyStructSequence_Desc times_result_desc = { + "times_result", /* name */ + times_result__doc__, /* doc */ + times_result_fields, + 5 +}; + +static PyTypeObject TimesResultType; + +#ifdef MS_WINDOWS +#define HAVE_TIMES /* mandatory, for the method table */ +#endif + +#ifdef HAVE_TIMES + +static PyObject * +build_times_result(double user, double system, + double children_user, double children_system, + double elapsed) +{ + PyObject *value = PyStructSequence_New(&TimesResultType); + if (value == NULL) + return NULL; + +#define SET(i, field) \ + { \ + PyObject *o = PyFloat_FromDouble(field); \ + if (!o) { \ + Py_DECREF(value); \ + return NULL; \ + } \ + PyStructSequence_SET_ITEM(value, i, o); \ + } \ + + SET(0, user); + SET(1, system); + SET(2, children_user); + SET(3, children_system); + SET(4, elapsed); + +#undef SET + + return value; +} + + +#ifndef MS_WINDOWS +#define NEED_TICKS_PER_SECOND +static long ticks_per_second = -1; +#endif /* MS_WINDOWS */ + +/*[clinic input] +os.times + +Return a collection containing process timing information. + +The object returned behaves like a named tuple with these fields: + (utime, stime, cutime, cstime, elapsed_time) +All fields are floating point numbers. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_times__doc__, +"times($module, /)\n" +"--\n" +"\n" +"Return a collection containing process timing information.\n" +"\n" +"The object returned behaves like a named tuple with these fields:\n" +" (utime, stime, cutime, cstime, elapsed_time)\n" +"All fields are floating point numbers."); + +#define OS_TIMES_METHODDEF \ + {"times", (PyCFunction)os_times, METH_NOARGS, os_times__doc__}, + +static PyObject * +os_times_impl(PyModuleDef *module); + +static PyObject * +os_times(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_times_impl(module); +} + +static PyObject * +os_times_impl(PyModuleDef *module) +/*[clinic end generated code: output=b86896d031a9b768 input=2bf9df3d6ab2e48b]*/ +#ifdef MS_WINDOWS +{ + FILETIME create, exit, kernel, user; + HANDLE hProc; + hProc = GetCurrentProcess(); + GetProcessTimes(hProc, &create, &exit, &kernel, &user); + /* The fields of a FILETIME structure are the hi and lo part + of a 64-bit value expressed in 100 nanosecond units. + 1e7 is one second in such units; 1e-7 the inverse. + 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7. + */ + return build_times_result( + (double)(user.dwHighDateTime*429.4967296 + + user.dwLowDateTime*1e-7), + (double)(kernel.dwHighDateTime*429.4967296 + + kernel.dwLowDateTime*1e-7), + (double)0, + (double)0, + (double)0); +} +#else /* MS_WINDOWS */ +{ + + + struct tms t; + clock_t c; + errno = 0; + c = times(&t); + if (c == (clock_t) -1) + return posix_error(); + return build_times_result( + (double)t.tms_utime / ticks_per_second, + (double)t.tms_stime / ticks_per_second, + (double)t.tms_cutime / ticks_per_second, + (double)t.tms_cstime / ticks_per_second, + (double)c / ticks_per_second); +} +#endif /* MS_WINDOWS */ +#endif /* HAVE_TIMES */ + + +#ifdef HAVE_GETSID +/*[clinic input] +os.getsid + + pid: pid_t + / + +Call the system call getsid(pid) and return the result. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_getsid__doc__, +"getsid($module, pid, /)\n" +"--\n" +"\n" +"Call the system call getsid(pid) and return the result."); + +#define OS_GETSID_METHODDEF \ + {"getsid", (PyCFunction)os_getsid, METH_VARARGS, os_getsid__doc__}, + +static PyObject * +os_getsid_impl(PyModuleDef *module, pid_t pid); + +static PyObject * +os_getsid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + pid_t pid; + + if (!PyArg_ParseTuple(args, + "" _Py_PARSE_PID ":getsid", + &pid)) + goto exit; + return_value = os_getsid_impl(module, pid); + +exit: + return return_value; +} + +static PyObject * +os_getsid_impl(PyModuleDef *module, pid_t pid) +/*[clinic end generated code: output=ea8390f395f4e0e1 input=eeb2b923a30ce04e]*/ +{ + int sid; + sid = getsid(pid); + if (sid < 0) + return posix_error(); + return PyLong_FromLong((long)sid); +} +#endif /* HAVE_GETSID */ + + +#ifdef HAVE_SETSID +/*[clinic input] +os.setsid + +Call the system call setsid(). +[clinic start generated code]*/ + +PyDoc_STRVAR(os_setsid__doc__, +"setsid($module, /)\n" +"--\n" +"\n" +"Call the system call setsid()."); + +#define OS_SETSID_METHODDEF \ + {"setsid", (PyCFunction)os_setsid, METH_NOARGS, os_setsid__doc__}, + +static PyObject * +os_setsid_impl(PyModuleDef *module); + +static PyObject * +os_setsid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_setsid_impl(module); +} + +static PyObject * +os_setsid_impl(PyModuleDef *module) +/*[clinic end generated code: output=2a9a1435d8d764d5 input=5fff45858e2f0776]*/ +{ + if (setsid() < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETSID */ + + +#ifdef HAVE_SETPGID +/*[clinic input] +os.setpgid + + pid: pid_t + pgrp: pid_t + / + +Call the system call setpgid(pid, pgrp). +[clinic start generated code]*/ + +PyDoc_STRVAR(os_setpgid__doc__, +"setpgid($module, pid, pgrp, /)\n" +"--\n" +"\n" +"Call the system call setpgid(pid, pgrp)."); + +#define OS_SETPGID_METHODDEF \ + {"setpgid", (PyCFunction)os_setpgid, METH_VARARGS, os_setpgid__doc__}, + +static PyObject * +os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp); + +static PyObject * +os_setpgid(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + pid_t pid; + pid_t pgrp; + + if (!PyArg_ParseTuple(args, + "" _Py_PARSE_PID "" _Py_PARSE_PID ":setpgid", + &pid, &pgrp)) + goto exit; + return_value = os_setpgid_impl(module, pid, pgrp); + +exit: + return return_value; +} + +static PyObject * +os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp) +/*[clinic end generated code: output=7ad79b725f890e1f input=fceb395eca572e1a]*/ +{ + if (setpgid(pid, pgrp) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_SETPGID */ + + +#ifdef HAVE_TCGETPGRP +/*[clinic input] +os.tcgetpgrp + + fd: int + / + +Return the process group associated with the terminal specified by fd. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_tcgetpgrp__doc__, +"tcgetpgrp($module, fd, /)\n" +"--\n" +"\n" +"Return the process group associated with the terminal specified by fd."); + +#define OS_TCGETPGRP_METHODDEF \ + {"tcgetpgrp", (PyCFunction)os_tcgetpgrp, METH_VARARGS, os_tcgetpgrp__doc__}, + +static PyObject * +os_tcgetpgrp_impl(PyModuleDef *module, int fd); + +static PyObject * +os_tcgetpgrp(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + + if (!PyArg_ParseTuple(args, + "i:tcgetpgrp", + &fd)) + goto exit; + return_value = os_tcgetpgrp_impl(module, fd); + +exit: + return return_value; +} + +static PyObject * +os_tcgetpgrp_impl(PyModuleDef *module, int fd) +/*[clinic end generated code: output=abcf52ed4c8d22cb input=7f6c18eac10ada86]*/ +{ + pid_t pgid = tcgetpgrp(fd); + if (pgid < 0) + return posix_error(); + return PyLong_FromPid(pgid); +} +#endif /* HAVE_TCGETPGRP */ + + +#ifdef HAVE_TCSETPGRP +/*[clinic input] +os.tcsetpgrp + + fd: int + pgid: pid_t + / + +Set the process group associated with the terminal specified by fd. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_tcsetpgrp__doc__, +"tcsetpgrp($module, fd, pgid, /)\n" +"--\n" +"\n" +"Set the process group associated with the terminal specified by fd."); + +#define OS_TCSETPGRP_METHODDEF \ + {"tcsetpgrp", (PyCFunction)os_tcsetpgrp, METH_VARARGS, os_tcsetpgrp__doc__}, + +static PyObject * +os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid); + +static PyObject * +os_tcsetpgrp(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + pid_t pgid; + + if (!PyArg_ParseTuple(args, + "i" _Py_PARSE_PID ":tcsetpgrp", + &fd, &pgid)) + goto exit; + return_value = os_tcsetpgrp_impl(module, fd, pgid); + +exit: + return return_value; +} + +static PyObject * +os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid) +/*[clinic end generated code: output=76f9bb8fd00f20f5 input=5bdc997c6a619020]*/ +{ + if (tcsetpgrp(fd, pgid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* HAVE_TCSETPGRP */ + +/* Functions acting on file descriptors */ + +#ifdef O_CLOEXEC +extern int _Py_open_cloexec_works; +#endif + + +/*[clinic input] +os.open -> int + path: path_t + flags: int + mode: int = 0o777 + * + dir_fd: dir_fd(requires='openat') = None + +# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\ + +Open a file for low level IO. Returns a file descriptor (integer). + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_open__doc__, +"open($module, /, path, flags, mode=511, *, dir_fd=None)\n" +"--\n" +"\n" +"Open a file for low level IO. Returns a file descriptor (integer).\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_OPEN_METHODDEF \ + {"open", (PyCFunction)os_open, METH_VARARGS|METH_KEYWORDS, os_open__doc__}, + +static int +os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd); + +static PyObject * +os_open(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "flags", "mode", "dir_fd", NULL}; + path_t path = PATH_T_INITIALIZE("open", "path", 0, 0); + int flags; + int mode = 511; + int dir_fd = DEFAULT_DIR_FD; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&i|i$O&:open", _keywords, + path_converter, &path, &flags, &mode, OPENAT_DIR_FD_CONVERTER, &dir_fd)) + goto exit; + _return_value = os_open_impl(module, &path, flags, mode, dir_fd); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +static int +os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd) +/*[clinic end generated code: output=05b68fc4ed5e29c9 input=ad8623b29acd2934]*/ +{ + int fd; + int async_err = 0; + +#ifdef O_CLOEXEC + int *atomic_flag_works = &_Py_open_cloexec_works; +#elif !defined(MS_WINDOWS) + int *atomic_flag_works = NULL; +#endif + +#ifdef MS_WINDOWS + flags |= O_NOINHERIT; +#elif defined(O_CLOEXEC) + flags |= O_CLOEXEC; +#endif + + do { + Py_BEGIN_ALLOW_THREADS +#ifdef MS_WINDOWS + if (path->wide) + fd = _wopen(path->wide, flags, mode); + else +#endif +#ifdef HAVE_OPENAT + if (dir_fd != DEFAULT_DIR_FD) + fd = openat(dir_fd, path->narrow, flags, mode); + else +#endif + fd = open(path->narrow, flags, mode); + Py_END_ALLOW_THREADS + } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (fd == -1) { + if (!async_err) + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); + return -1; + } + +#ifndef MS_WINDOWS + if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} + + +/*[clinic input] +os.close + + fd: int + +Close a file descriptor. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_close__doc__, +"close($module, /, fd)\n" +"--\n" +"\n" +"Close a file descriptor."); + +#define OS_CLOSE_METHODDEF \ + {"close", (PyCFunction)os_close, METH_VARARGS|METH_KEYWORDS, os_close__doc__}, + +static PyObject * +os_close_impl(PyModuleDef *module, int fd); + +static PyObject * +os_close(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"fd", NULL}; + int fd; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:close", _keywords, + &fd)) + goto exit; + return_value = os_close_impl(module, fd); + +exit: + return return_value; +} + +static PyObject * +os_close_impl(PyModuleDef *module, int fd) +/*[clinic end generated code: output=927004e29ad55808 input=2bc42451ca5c3223]*/ +{ + int res; + if (!_PyVerify_fd(fd)) + return posix_error(); + /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ + * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html + * for more details. + */ + Py_BEGIN_ALLOW_THREADS + res = close(fd); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} + + +/*[clinic input] +os.closerange + + fd_low: int + fd_high: int + / + +Closes all file descriptors in [fd_low, fd_high), ignoring errors. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_closerange__doc__, +"closerange($module, fd_low, fd_high, /)\n" +"--\n" +"\n" +"Closes all file descriptors in [fd_low, fd_high), ignoring errors."); + +#define OS_CLOSERANGE_METHODDEF \ + {"closerange", (PyCFunction)os_closerange, METH_VARARGS, os_closerange__doc__}, + +static PyObject * +os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high); + +static PyObject * +os_closerange(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd_low; + int fd_high; + + if (!PyArg_ParseTuple(args, + "ii:closerange", + &fd_low, &fd_high)) + goto exit; + return_value = os_closerange_impl(module, fd_low, fd_high); + +exit: + return return_value; +} + +static PyObject * +os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high) +/*[clinic end generated code: output=0a929ece386811c3 input=5855a3d053ebd4ec]*/ +{ + int i; + Py_BEGIN_ALLOW_THREADS + for (i = fd_low; i < fd_high; i++) + if (_PyVerify_fd(i)) + close(i); + Py_END_ALLOW_THREADS + Py_RETURN_NONE; +} + + +/*[clinic input] +os.dup -> int + + fd: int + / + +Return a duplicate of a file descriptor. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_dup__doc__, +"dup($module, fd, /)\n" +"--\n" +"\n" +"Return a duplicate of a file descriptor."); + +#define OS_DUP_METHODDEF \ + {"dup", (PyCFunction)os_dup, METH_VARARGS, os_dup__doc__}, + +static int +os_dup_impl(PyModuleDef *module, int fd); + +static PyObject * +os_dup(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + int _return_value; + + if (!PyArg_ParseTuple(args, + "i:dup", + &fd)) + goto exit; + _return_value = os_dup_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +static int +os_dup_impl(PyModuleDef *module, int fd) +/*[clinic end generated code: output=75943e057b25e1bd input=6f10f7ea97f7852a]*/ +{ + return _Py_dup(fd); +} + + +/*[clinic input] +os.dup2 + fd: int + fd2: int + inheritable: bool=True + +Duplicate file descriptor. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_dup2__doc__, +"dup2($module, /, fd, fd2, inheritable=True)\n" +"--\n" +"\n" +"Duplicate file descriptor."); + +#define OS_DUP2_METHODDEF \ + {"dup2", (PyCFunction)os_dup2, METH_VARARGS|METH_KEYWORDS, os_dup2__doc__}, + +static PyObject * +os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable); + +static PyObject * +os_dup2(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"fd", "fd2", "inheritable", NULL}; + int fd; + int fd2; + int inheritable = 1; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "ii|p:dup2", _keywords, + &fd, &fd2, &inheritable)) + goto exit; + return_value = os_dup2_impl(module, fd, fd2, inheritable); + +exit: + return return_value; +} + +static PyObject * +os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable) +/*[clinic end generated code: output=531e482dd11a99a0 input=76e96f511be0352f]*/ +{ + int res; +#if defined(HAVE_DUP3) && \ + !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) + /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ + int dup3_works = -1; +#endif + + if (!_PyVerify_fd_dup2(fd, fd2)) + return posix_error(); + + /* dup2() can fail with EINTR if the target FD is already open, because it + * then has to be closed. See os_close_impl() for why we don't handle EINTR + * upon close(), and therefore below. + */ +#ifdef MS_WINDOWS + Py_BEGIN_ALLOW_THREADS + res = dup2(fd, fd2); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + + /* Character files like console cannot be make non-inheritable */ + if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { + close(fd2); + return NULL; + } + +#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC) + Py_BEGIN_ALLOW_THREADS + if (!inheritable) + res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2); + else + res = dup2(fd, fd2); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + +#else + +#ifdef HAVE_DUP3 + if (!inheritable && dup3_works != 0) { + Py_BEGIN_ALLOW_THREADS + res = dup3(fd, fd2, O_CLOEXEC); + Py_END_ALLOW_THREADS + if (res < 0) { + if (dup3_works == -1) + dup3_works = (errno != ENOSYS); + if (dup3_works) + return posix_error(); + } + } + + if (inheritable || dup3_works == 0) + { +#endif + Py_BEGIN_ALLOW_THREADS + res = dup2(fd, fd2); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + + if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { + close(fd2); + return NULL; + } +#ifdef HAVE_DUP3 + } +#endif + +#endif + + Py_RETURN_NONE; +} + + +#ifdef HAVE_LOCKF +/*[clinic input] +os.lockf + + fd: int + An open file descriptor. + command: int + One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST. + length: Py_off_t + The number of bytes to lock, starting at the current position. + / + +Apply, test or remove a POSIX lock on an open file descriptor. + +[clinic start generated code]*/ + +PyDoc_STRVAR(os_lockf__doc__, +"lockf($module, fd, command, length, /)\n" +"--\n" +"\n" +"Apply, test or remove a POSIX lock on an open file descriptor.\n" +"\n" +" fd\n" +" An open file descriptor.\n" +" command\n" +" One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.\n" +" length\n" +" The number of bytes to lock, starting at the current position."); + +#define OS_LOCKF_METHODDEF \ + {"lockf", (PyCFunction)os_lockf, METH_VARARGS, os_lockf__doc__}, + +static PyObject * +os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length); + +static PyObject * +os_lockf(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + int command; + Py_off_t length; + + if (!PyArg_ParseTuple(args, + "iiO&:lockf", + &fd, &command, Py_off_t_converter, &length)) + goto exit; + return_value = os_lockf_impl(module, fd, command, length); + +exit: + return return_value; +} + +static PyObject * +os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length) +/*[clinic end generated code: output=1b28346ac7335c0f input=65da41d2106e9b79]*/ +{ + int res; + + Py_BEGIN_ALLOW_THREADS + res = lockf(fd, command, length); + Py_END_ALLOW_THREADS + + if (res < 0) + return posix_error(); + + Py_RETURN_NONE; +} +#endif /* HAVE_LOCKF */ + + +/*[clinic input] +os.lseek -> Py_off_t + + fd: int + position: Py_off_t + how: int + / + +Set the position of a file descriptor. Return the new position. + +Return the new cursor position in number of bytes +relative to the beginning of the file. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_lseek__doc__, +"lseek($module, fd, position, how, /)\n" +"--\n" +"\n" +"Set the position of a file descriptor. Return the new position.\n" +"\n" +"Return the new cursor position in number of bytes\n" +"relative to the beginning of the file."); + +#define OS_LSEEK_METHODDEF \ + {"lseek", (PyCFunction)os_lseek, METH_VARARGS, os_lseek__doc__}, + +static Py_off_t +os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how); + +static PyObject * +os_lseek(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t position; + int how; + Py_off_t _return_value; + + if (!PyArg_ParseTuple(args, + "iO&i:lseek", + &fd, Py_off_t_converter, &position, &how)) + goto exit; + _return_value = os_lseek_impl(module, fd, position, how); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromPy_off_t(_return_value); + +exit: + return return_value; +} + +static Py_off_t +os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how) +/*[clinic end generated code: output=88cfc146f55667af input=902654ad3f96a6d3]*/ +{ + Py_off_t result; + + if (!_PyVerify_fd(fd)) { + posix_error(); + return -1; + } +#ifdef SEEK_SET + /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ + switch (how) { + case 0: how = SEEK_SET; break; + case 1: how = SEEK_CUR; break; + case 2: how = SEEK_END; break; + } +#endif /* SEEK_END */ + + if (PyErr_Occurred()) + return -1; + + if (!_PyVerify_fd(fd)) { + posix_error(); + return -1; + } + Py_BEGIN_ALLOW_THREADS +#ifdef MS_WINDOWS + result = _lseeki64(fd, position, how); +#else + result = lseek(fd, position, how); +#endif + Py_END_ALLOW_THREADS + if (result < 0) + posix_error(); + + return result; +} + + +/*[clinic input] +os.read + fd: int + length: Py_ssize_t + / + +Read from a file descriptor. Returns a bytes object. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_read__doc__, +"read($module, fd, length, /)\n" +"--\n" +"\n" +"Read from a file descriptor. Returns a bytes object."); + +#define OS_READ_METHODDEF \ + {"read", (PyCFunction)os_read, METH_VARARGS, os_read__doc__}, + +static PyObject * +os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length); + +static PyObject * +os_read(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + Py_ssize_t length; + + if (!PyArg_ParseTuple(args, + "in:read", + &fd, &length)) + goto exit; + return_value = os_read_impl(module, fd, length); + +exit: + return return_value; +} + +static PyObject * +os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length) +/*[clinic end generated code: output=1f3bc27260a24968 input=1df2eaa27c0bf1d3]*/ +{ + Py_ssize_t n; + int async_err = 0; + PyObject *buffer; + + if (length < 0) { + errno = EINVAL; + return posix_error(); + } + if (!_PyVerify_fd(fd)) + return posix_error(); + +#ifdef MS_WINDOWS + #define READ_CAST (int) + if (length > INT_MAX) + length = INT_MAX; +#else + #define READ_CAST +#endif + + buffer = PyBytes_FromStringAndSize((char *)NULL, length); + if (buffer == NULL) + return NULL; + + do { + Py_BEGIN_ALLOW_THREADS + n = read(fd, PyBytes_AS_STRING(buffer), READ_CAST length); + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (n < 0) { + Py_DECREF(buffer); + return (!async_err) ? posix_error() : NULL; + } + + if (n != length) + _PyBytes_Resize(&buffer, n); + + return buffer; +} + +#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ + || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV) +static Py_ssize_t +iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type) +{ + int i, j; + Py_ssize_t blen, total = 0; + + *iov = PyMem_New(struct iovec, cnt); + if (*iov == NULL) { + PyErr_NoMemory(); + return -1; + } + + *buf = PyMem_New(Py_buffer, cnt); + if (*buf == NULL) { + PyMem_Del(*iov); + PyErr_NoMemory(); + return -1; + } + + for (i = 0; i < cnt; i++) { + PyObject *item = PySequence_GetItem(seq, i); + if (item == NULL) + goto fail; + if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { + Py_DECREF(item); + goto fail; + } + Py_DECREF(item); + (*iov)[i].iov_base = (*buf)[i].buf; + blen = (*buf)[i].len; + (*iov)[i].iov_len = blen; + total += blen; + } + return total; + +fail: + PyMem_Del(*iov); + for (j = 0; j < i; j++) { + PyBuffer_Release(&(*buf)[j]); + } + PyMem_Del(*buf); + return -1; +} + +static void +iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) +{ + int i; + PyMem_Del(iov); + for (i = 0; i < cnt; i++) { + PyBuffer_Release(&buf[i]); + } + PyMem_Del(buf); +} +#endif + + +#ifdef HAVE_READV +/*[clinic input] +os.readv -> Py_ssize_t + + fd: int + buffers: object + / + +Read from a file descriptor fd into an iterable of buffers. + +The buffers should be mutable buffers accepting bytes. +readv will transfer data into each buffer until it is full +and then move on to the next buffer in the sequence to hold +the rest of the data. + +readv returns the total number of bytes read, +which may be less than the total capacity of all the buffers. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_readv__doc__, +"readv($module, fd, buffers, /)\n" +"--\n" +"\n" +"Read from a file descriptor fd into an iterable of buffers.\n" +"\n" +"The buffers should be mutable buffers accepting bytes.\n" +"readv will transfer data into each buffer until it is full\n" +"and then move on to the next buffer in the sequence to hold\n" +"the rest of the data.\n" +"\n" +"readv returns the total number of bytes read,\n" +"which may be less than the total capacity of all the buffers."); + +#define OS_READV_METHODDEF \ + {"readv", (PyCFunction)os_readv, METH_VARARGS, os_readv__doc__}, + +static Py_ssize_t +os_readv_impl(PyModuleDef *module, int fd, PyObject *buffers); + +static PyObject * +os_readv(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + PyObject *buffers; + Py_ssize_t _return_value; + + if (!PyArg_ParseTuple(args, + "iO:readv", + &fd, &buffers)) + goto exit; + _return_value = os_readv_impl(module, fd, buffers); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +static Py_ssize_t +os_readv_impl(PyModuleDef *module, int fd, PyObject *buffers) +/*[clinic end generated code: output=72748b1c32a6e2a1 input=e679eb5dbfa0357d]*/ +{ + int cnt; + Py_ssize_t n; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; + + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "readv() arg 2 must be a sequence"); + return -1; + } + + cnt = PySequence_Size(buffers); + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) + return -1; + + do { + Py_BEGIN_ALLOW_THREADS + n = readv(fd, iov, cnt); + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + iov_cleanup(iov, buf, cnt); + if (n < 0) { + if (!async_err) + posix_error(); + return -1; + } + + return n; +} +#endif /* HAVE_READV */ + + +#ifdef HAVE_PREAD +/*[clinic input] +# TODO length should be size_t! but Python doesn't support parsing size_t yet. +os.pread + + fd: int + length: int + offset: Py_off_t + / + +Read a number of bytes from a file descriptor starting at a particular offset. + +Read length bytes from file descriptor fd, starting at offset bytes from +the beginning of the file. The file offset remains unchanged. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_pread__doc__, +"pread($module, fd, length, offset, /)\n" +"--\n" +"\n" +"Read a number of bytes from a file descriptor starting at a particular offset.\n" +"\n" +"Read length bytes from file descriptor fd, starting at offset bytes from\n" +"the beginning of the file. The file offset remains unchanged."); + +#define OS_PREAD_METHODDEF \ + {"pread", (PyCFunction)os_pread, METH_VARARGS, os_pread__doc__}, + +static PyObject * +os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset); + +static PyObject * +os_pread(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + int length; + Py_off_t offset; + + if (!PyArg_ParseTuple(args, + "iiO&:pread", + &fd, &length, Py_off_t_converter, &offset)) + goto exit; + return_value = os_pread_impl(module, fd, length, offset); + +exit: + return return_value; +} + +static PyObject * +os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset) +/*[clinic end generated code: output=7b62bf6c06e20ae8 input=084948dcbaa35d4c]*/ +{ + Py_ssize_t n; + int async_err = 0; + PyObject *buffer; + + if (length < 0) { + errno = EINVAL; + return posix_error(); + } + buffer = PyBytes_FromStringAndSize((char *)NULL, length); + if (buffer == NULL) + return NULL; + if (!_PyVerify_fd(fd)) { + Py_DECREF(buffer); + return posix_error(); + } + + do { + Py_BEGIN_ALLOW_THREADS + n = pread(fd, PyBytes_AS_STRING(buffer), length, offset); + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (n < 0) { + Py_DECREF(buffer); + return (!async_err) ? posix_error() : NULL; + } + if (n != length) + _PyBytes_Resize(&buffer, n); + return buffer; +} +#endif /* HAVE_PREAD */ + + +/*[clinic input] +os.write -> Py_ssize_t + + fd: int + data: Py_buffer + / + +Write a bytes object to a file descriptor. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_write__doc__, +"write($module, fd, data, /)\n" +"--\n" +"\n" +"Write a bytes object to a file descriptor."); + +#define OS_WRITE_METHODDEF \ + {"write", (PyCFunction)os_write, METH_VARARGS, os_write__doc__}, + +static Py_ssize_t +os_write_impl(PyModuleDef *module, int fd, Py_buffer *data); + +static PyObject * +os_write(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + Py_buffer data = {NULL, NULL}; + Py_ssize_t _return_value; + + if (!PyArg_ParseTuple(args, + "iy*:write", + &fd, &data)) + goto exit; + _return_value = os_write_impl(module, fd, &data); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromSsize_t(_return_value); + +exit: + /* Cleanup for data */ + if (data.obj) + PyBuffer_Release(&data); + + return return_value; +} + +static Py_ssize_t +os_write_impl(PyModuleDef *module, int fd, Py_buffer *data) +/*[clinic end generated code: output=aeb96acfdd4d5112 input=3207e28963234f3c]*/ +{ + Py_ssize_t size; + int async_err = 0; + Py_ssize_t len = data->len; + + if (!_PyVerify_fd(fd)) { + posix_error(); + return -1; + } + + do { + Py_BEGIN_ALLOW_THREADS +#ifdef MS_WINDOWS + if (len > INT_MAX) + len = INT_MAX; + size = write(fd, data->buf, (int)len); +#else + size = write(fd, data->buf, len); +#endif + Py_END_ALLOW_THREADS + } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (size < 0) { + if (!async_err) + posix_error(); + return -1; + } + return size; +} + +#ifdef HAVE_SENDFILE +PyDoc_STRVAR(posix_sendfile__doc__, +"sendfile(out, in, offset, nbytes) -> byteswritten\n\ +sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\ + -> byteswritten\n\ +Copy nbytes bytes from file descriptor in to file descriptor out."); + +/* AC 3.5: don't bother converting, has optional group*/ +static PyObject * +posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict) +{ + int in, out; + Py_ssize_t ret; + int async_err = 0; + off_t offset; + +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) +#ifndef __APPLE__ + Py_ssize_t len; +#endif + PyObject *headers = NULL, *trailers = NULL; + Py_buffer *hbuf, *tbuf; + off_t sbytes; + struct sf_hdtr sf; + int flags = 0; + static char *keywords[] = {"out", "in", + "offset", "count", + "headers", "trailers", "flags", NULL}; + + sf.headers = NULL; + sf.trailers = NULL; + +#ifdef __APPLE__ + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile", + keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes, +#else + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile", + keywords, &out, &in, Py_off_t_converter, &offset, &len, +#endif + &headers, &trailers, &flags)) + return NULL; + if (headers != NULL) { + if (!PySequence_Check(headers)) { + PyErr_SetString(PyExc_TypeError, + "sendfile() headers must be a sequence or None"); + return NULL; + } else { + Py_ssize_t i = 0; /* Avoid uninitialized warning */ + sf.hdr_cnt = PySequence_Size(headers); + if (sf.hdr_cnt > 0 && + (i = iov_setup(&(sf.headers), &hbuf, + headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0) + return NULL; +#ifdef __APPLE__ + sbytes += i; +#endif + } + } + if (trailers != NULL) { + if (!PySequence_Check(trailers)) { + PyErr_SetString(PyExc_TypeError, + "sendfile() trailers must be a sequence or None"); + return NULL; + } else { + Py_ssize_t i = 0; /* Avoid uninitialized warning */ + sf.trl_cnt = PySequence_Size(trailers); + if (sf.trl_cnt > 0 && + (i = iov_setup(&(sf.trailers), &tbuf, + trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0) + return NULL; +#ifdef __APPLE__ + sbytes += i; +#endif + } + } + + do { + Py_BEGIN_ALLOW_THREADS +#ifdef __APPLE__ + ret = sendfile(in, out, offset, &sbytes, &sf, flags); +#else + ret = sendfile(in, out, offset, len, &sf, &sbytes, flags); +#endif + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (sf.headers != NULL) + iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); + if (sf.trailers != NULL) + iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); + + if (ret < 0) { + if ((errno == EAGAIN) || (errno == EBUSY)) { + if (sbytes != 0) { + // some data has been sent + goto done; + } + else { + // no data has been sent; upper application is supposed + // to retry on EAGAIN or EBUSY + return posix_error(); + } + } + return (!async_err) ? posix_error() : NULL; + } + goto done; + +done: + #if !defined(HAVE_LARGEFILE_SUPPORT) + return Py_BuildValue("l", sbytes); + #else + return Py_BuildValue("L", sbytes); + #endif + +#else + Py_ssize_t count; + PyObject *offobj; + static char *keywords[] = {"out", "in", + "offset", "count", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile", + keywords, &out, &in, &offobj, &count)) + return NULL; +#ifdef linux + if (offobj == Py_None) { + do { + Py_BEGIN_ALLOW_THREADS + ret = sendfile(out, in, NULL, count); + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (ret < 0) + return (!async_err) ? posix_error() : NULL; + return Py_BuildValue("n", ret); + } +#endif + if (!Py_off_t_converter(offobj, &offset)) + return NULL; + + do { + Py_BEGIN_ALLOW_THREADS + ret = sendfile(out, in, &offset, count); + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (ret < 0) + return (!async_err) ? posix_error() : NULL; + return Py_BuildValue("n", ret); +#endif +} +#endif /* HAVE_SENDFILE */ + + +/*[clinic input] +os.fstat + + fd : int + +Perform a stat system call on the given file descriptor. + +Like stat(), but for an open file descriptor. +Equivalent to os.stat(fd). +[clinic start generated code]*/ + +PyDoc_STRVAR(os_fstat__doc__, +"fstat($module, /, fd)\n" +"--\n" +"\n" +"Perform a stat system call on the given file descriptor.\n" +"\n" +"Like stat(), but for an open file descriptor.\n" +"Equivalent to os.stat(fd)."); + +#define OS_FSTAT_METHODDEF \ + {"fstat", (PyCFunction)os_fstat, METH_VARARGS|METH_KEYWORDS, os_fstat__doc__}, + +static PyObject * +os_fstat_impl(PyModuleDef *module, int fd); + +static PyObject * +os_fstat(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"fd", NULL}; + int fd; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:fstat", _keywords, + &fd)) + goto exit; + return_value = os_fstat_impl(module, fd); + +exit: + return return_value; +} + +static PyObject * +os_fstat_impl(PyModuleDef *module, int fd) +/*[clinic end generated code: output=dae4a9678c7bd881 input=27e0e0ebbe5600c9]*/ +{ + STRUCT_STAT st; + int res; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + res = FSTAT(fd, &st); + Py_END_ALLOW_THREADS + } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + if (res != 0) { +#ifdef MS_WINDOWS + return PyErr_SetFromWindowsErr(0); +#else + return (!async_err) ? posix_error() : NULL; +#endif + } + + return _pystat_fromstructstat(&st); +} + + +/*[clinic input] +os.isatty -> bool + fd: int + / + +Return True if the fd is connected to a terminal. + +Return True if the file descriptor is an open file descriptor +connected to the slave end of a terminal. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_isatty__doc__, +"isatty($module, fd, /)\n" +"--\n" +"\n" +"Return True if the fd is connected to a terminal.\n" +"\n" +"Return True if the file descriptor is an open file descriptor\n" +"connected to the slave end of a terminal."); + +#define OS_ISATTY_METHODDEF \ + {"isatty", (PyCFunction)os_isatty, METH_VARARGS, os_isatty__doc__}, + +static int +os_isatty_impl(PyModuleDef *module, int fd); + +static PyObject * +os_isatty(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + int _return_value; + + if (!PyArg_ParseTuple(args, + "i:isatty", + &fd)) + goto exit; + _return_value = os_isatty_impl(module, fd); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +static int +os_isatty_impl(PyModuleDef *module, int fd) +/*[clinic end generated code: output=4bfadbfe22715097 input=08ce94aa1eaf7b5e]*/ +{ + if (!_PyVerify_fd(fd)) + return 0; + return isatty(fd); +} + + +#ifdef HAVE_PIPE +/*[clinic input] +os.pipe + +Create a pipe. + +Returns a tuple of two file descriptors: + (read_fd, write_fd) +[clinic start generated code]*/ + +PyDoc_STRVAR(os_pipe__doc__, +"pipe($module, /)\n" +"--\n" +"\n" +"Create a pipe.\n" +"\n" +"Returns a tuple of two file descriptors:\n" +" (read_fd, write_fd)"); + +#define OS_PIPE_METHODDEF \ + {"pipe", (PyCFunction)os_pipe, METH_NOARGS, os_pipe__doc__}, + +static PyObject * +os_pipe_impl(PyModuleDef *module); + +static PyObject * +os_pipe(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) +{ + return os_pipe_impl(module); +} + +static PyObject * +os_pipe_impl(PyModuleDef *module) +/*[clinic end generated code: output=0da2479f2266e774 input=02535e8c8fa6c4d4]*/ +{ + int fds[2]; +#ifdef MS_WINDOWS + HANDLE read, write; + SECURITY_ATTRIBUTES attr; + BOOL ok; +#else + int res; +#endif + +#ifdef MS_WINDOWS + attr.nLength = sizeof(attr); + attr.lpSecurityDescriptor = NULL; + attr.bInheritHandle = FALSE; + + Py_BEGIN_ALLOW_THREADS + ok = CreatePipe(&read, &write, &attr, 0); + if (ok) { + fds[0] = _open_osfhandle((Py_intptr_t)read, _O_RDONLY); + fds[1] = _open_osfhandle((Py_intptr_t)write, _O_WRONLY); + if (fds[0] == -1 || fds[1] == -1) { + CloseHandle(read); + CloseHandle(write); + ok = 0; + } + } + Py_END_ALLOW_THREADS + + if (!ok) + return PyErr_SetFromWindowsErr(0); +#else + +#ifdef HAVE_PIPE2 + Py_BEGIN_ALLOW_THREADS + res = pipe2(fds, O_CLOEXEC); + Py_END_ALLOW_THREADS + + if (res != 0 && errno == ENOSYS) + { +#endif + Py_BEGIN_ALLOW_THREADS + res = pipe(fds); + Py_END_ALLOW_THREADS + + if (res == 0) { + if (_Py_set_inheritable(fds[0], 0, NULL) < 0) { + close(fds[0]); + close(fds[1]); + return NULL; + } + if (_Py_set_inheritable(fds[1], 0, NULL) < 0) { + close(fds[0]); + close(fds[1]); + return NULL; + } + } +#ifdef HAVE_PIPE2 + } +#endif + + if (res != 0) + return PyErr_SetFromErrno(PyExc_OSError); +#endif /* !MS_WINDOWS */ + return Py_BuildValue("(ii)", fds[0], fds[1]); +} +#endif /* HAVE_PIPE */ + + +#ifdef HAVE_PIPE2 +/*[clinic input] +os.pipe2 + + flags: int + / + +Create a pipe with flags set atomically. + +Returns a tuple of two file descriptors: + (read_fd, write_fd) + +flags can be constructed by ORing together one or more of these values: +O_NONBLOCK, O_CLOEXEC. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_pipe2__doc__, +"pipe2($module, flags, /)\n" +"--\n" +"\n" +"Create a pipe with flags set atomically.\n" +"\n" +"Returns a tuple of two file descriptors:\n" +" (read_fd, write_fd)\n" +"\n" +"flags can be constructed by ORing together one or more of these values:\n" +"O_NONBLOCK, O_CLOEXEC."); + +#define OS_PIPE2_METHODDEF \ + {"pipe2", (PyCFunction)os_pipe2, METH_VARARGS, os_pipe2__doc__}, + +static PyObject * +os_pipe2_impl(PyModuleDef *module, int flags); + +static PyObject * +os_pipe2(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int flags; + + if (!PyArg_ParseTuple(args, + "i:pipe2", + &flags)) + goto exit; + return_value = os_pipe2_impl(module, flags); + +exit: + return return_value; +} + +static PyObject * +os_pipe2_impl(PyModuleDef *module, int flags) +/*[clinic end generated code: output=9e27c799ce19220b input=f261b6e7e63c6817]*/ +{ + int fds[2]; + int res; + + res = pipe2(fds, flags); + if (res != 0) + return posix_error(); + return Py_BuildValue("(ii)", fds[0], fds[1]); +} +#endif /* HAVE_PIPE2 */ + + +#ifdef HAVE_WRITEV +/*[clinic input] +os.writev -> Py_ssize_t + fd: int + buffers: object + / + +Iterate over buffers, and write the contents of each to a file descriptor. + +Returns the total number of bytes written. +buffers must be a sequence of bytes-like objects. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_writev__doc__, +"writev($module, fd, buffers, /)\n" +"--\n" +"\n" +"Iterate over buffers, and write the contents of each to a file descriptor.\n" +"\n" +"Returns the total number of bytes written.\n" +"buffers must be a sequence of bytes-like objects."); + +#define OS_WRITEV_METHODDEF \ + {"writev", (PyCFunction)os_writev, METH_VARARGS, os_writev__doc__}, + +static Py_ssize_t +os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers); + +static PyObject * +os_writev(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + PyObject *buffers; + Py_ssize_t _return_value; + + if (!PyArg_ParseTuple(args, + "iO:writev", + &fd, &buffers)) + goto exit; + _return_value = os_writev_impl(module, fd, buffers); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromSsize_t(_return_value); + +exit: + return return_value; +} + +static Py_ssize_t +os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers) +/*[clinic end generated code: output=591c662dccbe4951 input=5b8d17fe4189d2fe]*/ +{ + int cnt; + Py_ssize_t result; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; + + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "writev() arg 2 must be a sequence"); + return -1; + } + cnt = PySequence_Size(buffers); + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; + } + + do { + Py_BEGIN_ALLOW_THREADS + result = writev(fd, iov, cnt); + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + iov_cleanup(iov, buf, cnt); + if (result < 0 && !async_err) + posix_error(); + + return result; +} +#endif /* HAVE_WRITEV */ + + +#ifdef HAVE_PWRITE +/*[clinic input] +os.pwrite -> Py_ssize_t + + fd: int + buffer: Py_buffer + offset: Py_off_t + / + +Write bytes to a file descriptor starting at a particular offset. + +Write buffer to fd, starting at offset bytes from the beginning of +the file. Returns the number of bytes writte. Does not change the +current file offset. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_pwrite__doc__, +"pwrite($module, fd, buffer, offset, /)\n" +"--\n" +"\n" +"Write bytes to a file descriptor starting at a particular offset.\n" +"\n" +"Write buffer to fd, starting at offset bytes from the beginning of\n" +"the file. Returns the number of bytes writte. Does not change the\n" +"current file offset."); + +#define OS_PWRITE_METHODDEF \ + {"pwrite", (PyCFunction)os_pwrite, METH_VARARGS, os_pwrite__doc__}, + +static Py_ssize_t +os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset); + +static PyObject * +os_pwrite(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + Py_buffer buffer = {NULL, NULL}; + Py_off_t offset; + Py_ssize_t _return_value; + + if (!PyArg_ParseTuple(args, + "iy*O&:pwrite", + &fd, &buffer, Py_off_t_converter, &offset)) + goto exit; + _return_value = os_pwrite_impl(module, fd, &buffer, offset); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromSsize_t(_return_value); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) + PyBuffer_Release(&buffer); + + return return_value; +} + +static Py_ssize_t +os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset) +/*[clinic end generated code: output=ec9cc5b2238e96a7 input=19903f1b3dd26377]*/ +{ + Py_ssize_t size; + int async_err = 0; + + if (!_PyVerify_fd(fd)) { + posix_error(); + return -1; + } + + do { + Py_BEGIN_ALLOW_THREADS + size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); + Py_END_ALLOW_THREADS + } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (size < 0 && !async_err) + posix_error(); + return size; +} +#endif /* HAVE_PWRITE */ + + +#ifdef HAVE_MKFIFO +/*[clinic input] +os.mkfifo + + path: path_t + mode: int=0o666 + * + dir_fd: dir_fd(requires='mkfifoat')=None + +Create a "fifo" (a POSIX named pipe). + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_mkfifo__doc__, +"mkfifo($module, /, path, mode=438, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a \"fifo\" (a POSIX named pipe).\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_MKFIFO_METHODDEF \ + {"mkfifo", (PyCFunction)os_mkfifo, METH_VARARGS|METH_KEYWORDS, os_mkfifo__doc__}, + +static PyObject * +os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd); + +static PyObject * +os_mkfifo(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "mode", "dir_fd", NULL}; + path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0); + int mode = 438; + int dir_fd = DEFAULT_DIR_FD; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&|i$O&:mkfifo", _keywords, + path_converter, &path, &mode, MKFIFOAT_DIR_FD_CONVERTER, &dir_fd)) + goto exit; + return_value = os_mkfifo_impl(module, &path, mode, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +static PyObject * +os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd) +/*[clinic end generated code: output=b3321927546893d0 input=73032e98a36e0e19]*/ +{ + int result; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_MKFIFOAT + if (dir_fd != DEFAULT_DIR_FD) + result = mkfifoat(dir_fd, path->narrow, mode); + else +#endif + result = mkfifo(path->narrow, mode); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + + Py_RETURN_NONE; +} +#endif /* HAVE_MKFIFO */ + + +#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) +/*[clinic input] +os.mknod + + path: path_t + mode: int=0o600 + device: dev_t=0 + * + dir_fd: dir_fd(requires='mknodat')=None + +Create a node in the file system. + +Create a node in the file system (file, device special file or named pipe) +at path. mode specifies both the permissions to use and the +type of node to be created, being combined (bitwise OR) with one of +S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode, +device defines the newly created device special file (probably using +os.makedev()). Otherwise device is ignored. + +If dir_fd is not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that directory. +dir_fd may not be implemented on your platform. + If it is unavailable, using it will raise a NotImplementedError. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_mknod__doc__, +"mknod($module, /, path, mode=384, device=0, *, dir_fd=None)\n" +"--\n" +"\n" +"Create a node in the file system.\n" +"\n" +"Create a node in the file system (file, device special file or named pipe)\n" +"at path. mode specifies both the permissions to use and the\n" +"type of node to be created, being combined (bitwise OR) with one of\n" +"S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,\n" +"device defines the newly created device special file (probably using\n" +"os.makedev()). Otherwise device is ignored.\n" +"\n" +"If dir_fd is not None, it should be a file descriptor open to a directory,\n" +" and path should be relative; path will then be relative to that directory.\n" +"dir_fd may not be implemented on your platform.\n" +" If it is unavailable, using it will raise a NotImplementedError."); + +#define OS_MKNOD_METHODDEF \ + {"mknod", (PyCFunction)os_mknod, METH_VARARGS|METH_KEYWORDS, os_mknod__doc__}, + +static PyObject * +os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd); + +static PyObject * +os_mknod(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "mode", "device", "dir_fd", NULL}; + path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0); + int mode = 384; + dev_t device = 0; + int dir_fd = DEFAULT_DIR_FD; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&|iO&$O&:mknod", _keywords, + path_converter, &path, &mode, _Py_Dev_Converter, &device, MKNODAT_DIR_FD_CONVERTER, &dir_fd)) + goto exit; + return_value = os_mknod_impl(module, &path, mode, device, dir_fd); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +static PyObject * +os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd) +/*[clinic end generated code: output=f71d54eaf9bb6f1a input=ee44531551a4d83b]*/ +{ + int result; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_MKNODAT + if (dir_fd != DEFAULT_DIR_FD) + result = mknodat(dir_fd, path->narrow, mode, device); + else +#endif + result = mknod(path->narrow, mode, device); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + + Py_RETURN_NONE; +} +#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ + + +#ifdef HAVE_DEVICE_MACROS +/*[clinic input] +os.major -> unsigned_int + + device: dev_t + / + +Extracts a device major number from a raw device number. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_major__doc__, +"major($module, device, /)\n" +"--\n" +"\n" +"Extracts a device major number from a raw device number."); + +#define OS_MAJOR_METHODDEF \ + {"major", (PyCFunction)os_major, METH_VARARGS, os_major__doc__}, + +static unsigned int +os_major_impl(PyModuleDef *module, dev_t device); + +static PyObject * +os_major(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + dev_t device; + unsigned int _return_value; + + if (!PyArg_ParseTuple(args, + "O&:major", + _Py_Dev_Converter, &device)) + goto exit; + _return_value = os_major_impl(module, device); + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); + +exit: + return return_value; +} + +static unsigned int +os_major_impl(PyModuleDef *module, dev_t device) +/*[clinic end generated code: output=a2d06e908ebf95b5 input=1e16a4d30c4d4462]*/ +{ + return major(device); +} + + +/*[clinic input] +os.minor -> unsigned_int + + device: dev_t + / + +Extracts a device minor number from a raw device number. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_minor__doc__, +"minor($module, device, /)\n" +"--\n" +"\n" +"Extracts a device minor number from a raw device number."); + +#define OS_MINOR_METHODDEF \ + {"minor", (PyCFunction)os_minor, METH_VARARGS, os_minor__doc__}, + +static unsigned int +os_minor_impl(PyModuleDef *module, dev_t device); + +static PyObject * +os_minor(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + dev_t device; + unsigned int _return_value; + + if (!PyArg_ParseTuple(args, + "O&:minor", + _Py_Dev_Converter, &device)) + goto exit; + _return_value = os_minor_impl(module, device); + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); + +exit: + return return_value; +} + +static unsigned int +os_minor_impl(PyModuleDef *module, dev_t device) +/*[clinic end generated code: output=6332287ee3f006e2 input=0842c6d23f24c65e]*/ +{ + return minor(device); +} + + +/*[clinic input] +os.makedev -> dev_t + + major: int + minor: int + / + +Composes a raw device number from the major and minor device numbers. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_makedev__doc__, +"makedev($module, major, minor, /)\n" +"--\n" +"\n" +"Composes a raw device number from the major and minor device numbers."); + +#define OS_MAKEDEV_METHODDEF \ + {"makedev", (PyCFunction)os_makedev, METH_VARARGS, os_makedev__doc__}, + +static dev_t +os_makedev_impl(PyModuleDef *module, int major, int minor); + +static PyObject * +os_makedev(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int major; + int minor; + dev_t _return_value; + + if (!PyArg_ParseTuple(args, + "ii:makedev", + &major, &minor)) + goto exit; + _return_value = os_makedev_impl(module, major, minor); + if ((_return_value == (dev_t)-1) && PyErr_Occurred()) + goto exit; + return_value = _PyLong_FromDev(_return_value); + +exit: + return return_value; +} + +static dev_t +os_makedev_impl(PyModuleDef *module, int major, int minor) +/*[clinic end generated code: output=38e9a9774c96511a input=4b9fd8fc73cbe48f]*/ +{ + return makedev(major, minor); +} +#endif /* HAVE_DEVICE_MACROS */ + + +#ifdef HAVE_FTRUNCATE +/*[clinic input] +os.ftruncate + + fd: int + length: Py_off_t + / + +Truncate a file, specified by file descriptor, to a specific length. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_ftruncate__doc__, +"ftruncate($module, fd, length, /)\n" +"--\n" +"\n" +"Truncate a file, specified by file descriptor, to a specific length."); + +#define OS_FTRUNCATE_METHODDEF \ + {"ftruncate", (PyCFunction)os_ftruncate, METH_VARARGS, os_ftruncate__doc__}, + +static PyObject * +os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length); + +static PyObject * +os_ftruncate(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t length; + + if (!PyArg_ParseTuple(args, + "iO&:ftruncate", + &fd, Py_off_t_converter, &length)) + goto exit; + return_value = os_ftruncate_impl(module, fd, length); + +exit: + return return_value; +} + +static PyObject * +os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length) +/*[clinic end generated code: output=62326766cb9b76bf input=63b43641e52818f2]*/ +{ + int result; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + result = ftruncate(fd, length); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + Py_RETURN_NONE; +} +#endif /* HAVE_FTRUNCATE */ + + +#ifdef HAVE_TRUNCATE +/*[clinic input] +os.truncate + path: path_t(allow_fd='PATH_HAVE_FTRUNCATE') + length: Py_off_t + +Truncate a file, specified by path, to a specific length. + +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_truncate__doc__, +"truncate($module, /, path, length)\n" +"--\n" +"\n" +"Truncate a file, specified by path, to a specific length.\n" +"\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_TRUNCATE_METHODDEF \ + {"truncate", (PyCFunction)os_truncate, METH_VARARGS|METH_KEYWORDS, os_truncate__doc__}, + +static PyObject * +os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length); + +static PyObject * +os_truncate(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "length", NULL}; + path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE); + Py_off_t length; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&O&:truncate", _keywords, + path_converter, &path, Py_off_t_converter, &length)) + goto exit; + return_value = os_truncate_impl(module, &path, length); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +static PyObject * +os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length) +/*[clinic end generated code: output=6bd76262d2e027c6 input=77229cf0b50a9b77]*/ +{ + int result; + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FTRUNCATE + if (path->fd != -1) + result = ftruncate(path->fd, length); + else +#endif + result = truncate(path->narrow, length); + Py_END_ALLOW_THREADS + if (result < 0) + return path_error(path); + + Py_RETURN_NONE; +} +#endif /* HAVE_TRUNCATE */ + + +/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() + and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is + defined, which is the case in Python on AIX. AIX bug report: + http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ +#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) +# define POSIX_FADVISE_AIX_BUG +#endif + + +#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) +/*[clinic input] +os.posix_fallocate + + fd: int + offset: Py_off_t + length: Py_off_t + / + +Ensure a file has allocated at least a particular number of bytes on disk. + +Ensure that the file specified by fd encompasses a range of bytes +starting at offset bytes from the beginning and continuing for length bytes. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_posix_fallocate__doc__, +"posix_fallocate($module, fd, offset, length, /)\n" +"--\n" +"\n" +"Ensure a file has allocated at least a particular number of bytes on disk.\n" +"\n" +"Ensure that the file specified by fd encompasses a range of bytes\n" +"starting at offset bytes from the beginning and continuing for length bytes."); + +#define OS_POSIX_FALLOCATE_METHODDEF \ + {"posix_fallocate", (PyCFunction)os_posix_fallocate, METH_VARARGS, os_posix_fallocate__doc__}, + +static PyObject * +os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length); + +static PyObject * +os_posix_fallocate(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t offset; + Py_off_t length; + + if (!PyArg_ParseTuple(args, + "iO&O&:posix_fallocate", + &fd, Py_off_t_converter, &offset, Py_off_t_converter, &length)) + goto exit; + return_value = os_posix_fallocate_impl(module, fd, offset, length); + +exit: + return return_value; +} + +static PyObject * +os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length) +/*[clinic end generated code: output=0cd702d2065c79db input=d7a2ef0ab2ca52fb]*/ +{ + int result; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + result = posix_fallocate(fd, offset, length); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + Py_RETURN_NONE; +} +#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */ + + +#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) +/*[clinic input] +os.posix_fadvise + + fd: int + offset: Py_off_t + length: Py_off_t + advice: int + / + +Announce an intention to access data in a specific pattern. + +Announce an intention to access data in a specific pattern, thus allowing +the kernel to make optimizations. +The advice applies to the region of the file specified by fd starting at +offset and continuing for length bytes. +advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, +POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or +POSIX_FADV_DONTNEED. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_posix_fadvise__doc__, +"posix_fadvise($module, fd, offset, length, advice, /)\n" +"--\n" +"\n" +"Announce an intention to access data in a specific pattern.\n" +"\n" +"Announce an intention to access data in a specific pattern, thus allowing\n" +"the kernel to make optimizations.\n" +"The advice applies to the region of the file specified by fd starting at\n" +"offset and continuing for length bytes.\n" +"advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n" +"POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or\n" +"POSIX_FADV_DONTNEED."); + +#define OS_POSIX_FADVISE_METHODDEF \ + {"posix_fadvise", (PyCFunction)os_posix_fadvise, METH_VARARGS, os_posix_fadvise__doc__}, + +static PyObject * +os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice); + +static PyObject * +os_posix_fadvise(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + Py_off_t offset; + Py_off_t length; + int advice; + + if (!PyArg_ParseTuple(args, + "iO&O&i:posix_fadvise", + &fd, Py_off_t_converter, &offset, Py_off_t_converter, &length, &advice)) + goto exit; + return_value = os_posix_fadvise_impl(module, fd, offset, length, advice); + +exit: + return return_value; +} + +static PyObject * +os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice) +/*[clinic end generated code: output=dad93f32c04dd4f7 input=0fbe554edc2f04b5]*/ +{ + int result; + int async_err = 0; + + do { + Py_BEGIN_ALLOW_THREADS + result = posix_fadvise(fd, offset, length, advice); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + Py_RETURN_NONE; +} +#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ + +#ifdef HAVE_PUTENV + +/* Save putenv() parameters as values here, so we can collect them when they + * get re-set with another call for the same key. */ +static PyObject *posix_putenv_garbage; + +static void +posix_putenv_garbage_setitem(PyObject *name, PyObject *value) +{ + /* Install the first arg and newstr in posix_putenv_garbage; + * this will cause previous value to be collected. This has to + * happen after the real putenv() call because the old value + * was still accessible until then. */ + if (PyDict_SetItem(posix_putenv_garbage, name, value)) + /* really not much we can do; just leak */ + PyErr_Clear(); + else + Py_DECREF(value); +} + + +#ifdef MS_WINDOWS +/*[clinic input] +os.putenv + + name: unicode + value: unicode + / + +Change or add an environment variable. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_putenv__doc__, +"putenv($module, name, value, /)\n" +"--\n" +"\n" +"Change or add an environment variable."); + +#define OS_PUTENV_METHODDEF \ + {"putenv", (PyCFunction)os_putenv, METH_VARARGS, os_putenv__doc__}, + +static PyObject * +os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value); + +static PyObject * +os_putenv(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *name; + PyObject *value; + + if (!PyArg_ParseTuple(args, + "UU:putenv", + &name, &value)) + goto exit; + return_value = os_putenv_impl(module, name, value); + +exit: + return return_value; +} + +static PyObject * +os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value) +/*[clinic end generated code: output=5ce9ef9b15606e7e input=ba586581c2e6105f]*/ +{ + wchar_t *env; + + PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value); + if (unicode == NULL) { + PyErr_NoMemory(); + return NULL; + } + if (_MAX_ENV < PyUnicode_GET_LENGTH(unicode)) { + PyErr_Format(PyExc_ValueError, + "the environment variable is longer than %u characters", + _MAX_ENV); + goto error; + } + + env = PyUnicode_AsUnicode(unicode); + if (env == NULL) + goto error; + if (_wputenv(env)) { + posix_error(); + goto error; + } + + posix_putenv_garbage_setitem(name, unicode); + Py_RETURN_NONE; + +error: + Py_DECREF(unicode); + return NULL; +} +#else /* MS_WINDOWS */ +/*[clinic input] +os.putenv + + name: FSConverter + value: FSConverter + / + +Change or add an environment variable. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_putenv__doc__, +"putenv($module, name, value, /)\n" +"--\n" +"\n" +"Change or add an environment variable."); + +#define OS_PUTENV_METHODDEF \ + {"putenv", (PyCFunction)os_putenv, METH_VARARGS, os_putenv__doc__}, + +static PyObject * +os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value); + +static PyObject * +os_putenv(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *name = NULL; + PyObject *value = NULL; + + if (!PyArg_ParseTuple(args, + "O&O&:putenv", + PyUnicode_FSConverter, &name, PyUnicode_FSConverter, &value)) + goto exit; + return_value = os_putenv_impl(module, name, value); + +exit: + /* Cleanup for name */ + Py_XDECREF(name); + /* Cleanup for value */ + Py_XDECREF(value); + + return return_value; +} + +static PyObject * +os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value) +/*[clinic end generated code: output=85ab223393dc7afd input=a97bc6152f688d31]*/ +{ + PyObject *bytes = NULL; + char *env; + char *name_string = PyBytes_AsString(name); + char *value_string = PyBytes_AsString(value); + + bytes = PyBytes_FromFormat("%s=%s", name_string, value_string); + if (bytes == NULL) { + PyErr_NoMemory(); + return NULL; + } + + env = PyBytes_AS_STRING(bytes); + if (putenv(env)) { + Py_DECREF(bytes); + return posix_error(); + } + + posix_putenv_garbage_setitem(name, bytes); + Py_RETURN_NONE; +} +#endif /* MS_WINDOWS */ +#endif /* HAVE_PUTENV */ + + +#ifdef HAVE_UNSETENV +/*[clinic input] +os.unsetenv + name: FSConverter + / + +Delete an environment variable. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_unsetenv__doc__, +"unsetenv($module, name, /)\n" +"--\n" +"\n" +"Delete an environment variable."); + +#define OS_UNSETENV_METHODDEF \ + {"unsetenv", (PyCFunction)os_unsetenv, METH_VARARGS, os_unsetenv__doc__}, + +static PyObject * +os_unsetenv_impl(PyModuleDef *module, PyObject *name); + +static PyObject * +os_unsetenv(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *name = NULL; + + if (!PyArg_ParseTuple(args, + "O&:unsetenv", + PyUnicode_FSConverter, &name)) + goto exit; + return_value = os_unsetenv_impl(module, name); + +exit: + /* Cleanup for name */ + Py_XDECREF(name); + + return return_value; +} + +static PyObject * +os_unsetenv_impl(PyModuleDef *module, PyObject *name) +/*[clinic end generated code: output=91318c995f9a0767 input=2bb5288a599c7107]*/ +{ +#ifndef HAVE_BROKEN_UNSETENV + int err; +#endif + +#ifdef HAVE_BROKEN_UNSETENV + unsetenv(PyBytes_AS_STRING(name)); +#else + err = unsetenv(PyBytes_AS_STRING(name)); + if (err) + return posix_error(); +#endif + + /* Remove the key from posix_putenv_garbage; + * this will cause it to be collected. This has to + * happen after the real unsetenv() call because the + * old value was still accessible until then. + */ + if (PyDict_DelItem(posix_putenv_garbage, name)) { + /* really not much we can do; just leak */ + PyErr_Clear(); + } + Py_RETURN_NONE; +} +#endif /* HAVE_UNSETENV */ + + +/*[clinic input] +os.strerror + + code: int + / + +Translate an error code to a message string. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_strerror__doc__, +"strerror($module, code, /)\n" +"--\n" +"\n" +"Translate an error code to a message string."); + +#define OS_STRERROR_METHODDEF \ + {"strerror", (PyCFunction)os_strerror, METH_VARARGS, os_strerror__doc__}, + +static PyObject * +os_strerror_impl(PyModuleDef *module, int code); + +static PyObject * +os_strerror(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int code; + + if (!PyArg_ParseTuple(args, + "i:strerror", + &code)) + goto exit; + return_value = os_strerror_impl(module, code); + +exit: + return return_value; +} + +static PyObject * +os_strerror_impl(PyModuleDef *module, int code) +/*[clinic end generated code: output=8665c70bb2ca4720 input=75a8673d97915a91]*/ +{ + char *message = strerror(code); + if (message == NULL) { + PyErr_SetString(PyExc_ValueError, + "strerror() argument out of range"); + return NULL; + } + return PyUnicode_DecodeLocale(message, "surrogateescape"); +} + + +#ifdef HAVE_SYS_WAIT_H +#ifdef WCOREDUMP +/*[clinic input] +os.WCOREDUMP -> bool + + status: int + / + +Return True if the process returning status was dumped to a core file. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_WCOREDUMP__doc__, +"WCOREDUMP($module, status, /)\n" +"--\n" +"\n" +"Return True if the process returning status was dumped to a core file."); + +#define OS_WCOREDUMP_METHODDEF \ + {"WCOREDUMP", (PyCFunction)os_WCOREDUMP, METH_VARARGS, os_WCOREDUMP__doc__}, + +static int +os_WCOREDUMP_impl(PyModuleDef *module, int status); + +static PyObject * +os_WCOREDUMP(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int status; + int _return_value; + + if (!PyArg_ParseTuple(args, + "i:WCOREDUMP", + &status)) + goto exit; + _return_value = os_WCOREDUMP_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +static int +os_WCOREDUMP_impl(PyModuleDef *module, int status) +/*[clinic end generated code: output=e04d55c09c299828 input=8b05e7ab38528d04]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WCOREDUMP(wait_status); +} +#endif /* WCOREDUMP */ + + +#ifdef WIFCONTINUED +/*[clinic input] +os.WIFCONTINUED -> bool + + status: int + +Return True if a particular process was continued from a job control stop. + +Return True if the process returning status was continued from a +job control stop. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_WIFCONTINUED__doc__, +"WIFCONTINUED($module, /, status)\n" +"--\n" +"\n" +"Return True if a particular process was continued from a job control stop.\n" +"\n" +"Return True if the process returning status was continued from a\n" +"job control stop."); + +#define OS_WIFCONTINUED_METHODDEF \ + {"WIFCONTINUED", (PyCFunction)os_WIFCONTINUED, METH_VARARGS|METH_KEYWORDS, os_WIFCONTINUED__doc__}, + +static int +os_WIFCONTINUED_impl(PyModuleDef *module, int status); + +static PyObject * +os_WIFCONTINUED(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"status", NULL}; + int status; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:WIFCONTINUED", _keywords, + &status)) + goto exit; + _return_value = os_WIFCONTINUED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +static int +os_WIFCONTINUED_impl(PyModuleDef *module, int status) +/*[clinic end generated code: output=9c4e6105a4520ab5 input=e777e7d38eb25bd9]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFCONTINUED(wait_status); +} +#endif /* WIFCONTINUED */ + + +#ifdef WIFSTOPPED +/*[clinic input] +os.WIFSTOPPED -> bool + + status: int + +Return True if the process returning status was stopped. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_WIFSTOPPED__doc__, +"WIFSTOPPED($module, /, status)\n" +"--\n" +"\n" +"Return True if the process returning status was stopped."); + +#define OS_WIFSTOPPED_METHODDEF \ + {"WIFSTOPPED", (PyCFunction)os_WIFSTOPPED, METH_VARARGS|METH_KEYWORDS, os_WIFSTOPPED__doc__}, + +static int +os_WIFSTOPPED_impl(PyModuleDef *module, int status); + +static PyObject * +os_WIFSTOPPED(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"status", NULL}; + int status; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:WIFSTOPPED", _keywords, + &status)) + goto exit; + _return_value = os_WIFSTOPPED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +static int +os_WIFSTOPPED_impl(PyModuleDef *module, int status) +/*[clinic end generated code: output=e0de2da8ec9593ff input=043cb7f1289ef904]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFSTOPPED(wait_status); +} +#endif /* WIFSTOPPED */ + + +#ifdef WIFSIGNALED +/*[clinic input] +os.WIFSIGNALED -> bool + + status: int + +Return True if the process returning status was terminated by a signal. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_WIFSIGNALED__doc__, +"WIFSIGNALED($module, /, status)\n" +"--\n" +"\n" +"Return True if the process returning status was terminated by a signal."); + +#define OS_WIFSIGNALED_METHODDEF \ + {"WIFSIGNALED", (PyCFunction)os_WIFSIGNALED, METH_VARARGS|METH_KEYWORDS, os_WIFSIGNALED__doc__}, + +static int +os_WIFSIGNALED_impl(PyModuleDef *module, int status); + +static PyObject * +os_WIFSIGNALED(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"status", NULL}; + int status; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:WIFSIGNALED", _keywords, + &status)) + goto exit; + _return_value = os_WIFSIGNALED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +static int +os_WIFSIGNALED_impl(PyModuleDef *module, int status) +/*[clinic end generated code: output=f14d106558f406be input=d55ba7cc9ce5dc43]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFSIGNALED(wait_status); +} +#endif /* WIFSIGNALED */ + + +#ifdef WIFEXITED +/*[clinic input] +os.WIFEXITED -> bool + + status: int + +Return True if the process returning status exited via the exit() system call. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_WIFEXITED__doc__, +"WIFEXITED($module, /, status)\n" +"--\n" +"\n" +"Return True if the process returning status exited via the exit() system call."); + +#define OS_WIFEXITED_METHODDEF \ + {"WIFEXITED", (PyCFunction)os_WIFEXITED, METH_VARARGS|METH_KEYWORDS, os_WIFEXITED__doc__}, + +static int +os_WIFEXITED_impl(PyModuleDef *module, int status); + +static PyObject * +os_WIFEXITED(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"status", NULL}; + int status; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:WIFEXITED", _keywords, + &status)) + goto exit; + _return_value = os_WIFEXITED_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + +static int +os_WIFEXITED_impl(PyModuleDef *module, int status) +/*[clinic end generated code: output=2f76087d53721255 input=d63775a6791586c0]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFEXITED(wait_status); +} +#endif /* WIFEXITED */ + + +#ifdef WEXITSTATUS +/*[clinic input] +os.WEXITSTATUS -> int + + status: int + +Return the process return code from status. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_WEXITSTATUS__doc__, +"WEXITSTATUS($module, /, status)\n" +"--\n" +"\n" +"Return the process return code from status."); + +#define OS_WEXITSTATUS_METHODDEF \ + {"WEXITSTATUS", (PyCFunction)os_WEXITSTATUS, METH_VARARGS|METH_KEYWORDS, os_WEXITSTATUS__doc__}, + +static int +os_WEXITSTATUS_impl(PyModuleDef *module, int status); + +static PyObject * +os_WEXITSTATUS(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"status", NULL}; + int status; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:WEXITSTATUS", _keywords, + &status)) + goto exit; + _return_value = os_WEXITSTATUS_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +static int +os_WEXITSTATUS_impl(PyModuleDef *module, int status) +/*[clinic end generated code: output=13b6c270e2a326b1 input=e1fb4944e377585b]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WEXITSTATUS(wait_status); +} +#endif /* WEXITSTATUS */ + + +#ifdef WTERMSIG +/*[clinic input] +os.WTERMSIG -> int + + status: int + +Return the signal that terminated the process that provided the status value. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_WTERMSIG__doc__, +"WTERMSIG($module, /, status)\n" +"--\n" +"\n" +"Return the signal that terminated the process that provided the status value."); + +#define OS_WTERMSIG_METHODDEF \ + {"WTERMSIG", (PyCFunction)os_WTERMSIG, METH_VARARGS|METH_KEYWORDS, os_WTERMSIG__doc__}, + +static int +os_WTERMSIG_impl(PyModuleDef *module, int status); + +static PyObject * +os_WTERMSIG(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"status", NULL}; + int status; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:WTERMSIG", _keywords, + &status)) + goto exit; + _return_value = os_WTERMSIG_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +static int +os_WTERMSIG_impl(PyModuleDef *module, int status) +/*[clinic end generated code: output=bf1fd4b002d0a9ed input=727fd7f84ec3f243]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WTERMSIG(wait_status); +} +#endif /* WTERMSIG */ + + +#ifdef WSTOPSIG +/*[clinic input] +os.WSTOPSIG -> int + + status: int + +Return the signal that stopped the process that provided the status value. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_WSTOPSIG__doc__, +"WSTOPSIG($module, /, status)\n" +"--\n" +"\n" +"Return the signal that stopped the process that provided the status value."); + +#define OS_WSTOPSIG_METHODDEF \ + {"WSTOPSIG", (PyCFunction)os_WSTOPSIG, METH_VARARGS|METH_KEYWORDS, os_WSTOPSIG__doc__}, + +static int +os_WSTOPSIG_impl(PyModuleDef *module, int status); + +static PyObject * +os_WSTOPSIG(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"status", NULL}; + int status; + int _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i:WSTOPSIG", _keywords, + &status)) + goto exit; + _return_value = os_WSTOPSIG_impl(module, status); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +static int +os_WSTOPSIG_impl(PyModuleDef *module, int status) +/*[clinic end generated code: output=92e1647d29ee0549 input=46ebf1d1b293c5c1]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WSTOPSIG(wait_status); +} +#endif /* WSTOPSIG */ +#endif /* HAVE_SYS_WAIT_H */ + + +#ifndef OS_WCOREDUMP_METHODDEF +#define OS_WCOREDUMP_METHODDEF +#endif /* OS_WCOREDUMP_METHODDEF */ + +#ifndef OS_WIFCONTINUED_METHODDEF +#define OS_WIFCONTINUED_METHODDEF +#endif /* OS_WIFCONTINUED_METHODDEF */ + +#ifndef OS_WIFSTOPPED_METHODDEF +#define OS_WIFSTOPPED_METHODDEF +#endif /* OS_WIFSTOPPED_METHODDEF */ + +#ifndef OS_WIFSIGNALED_METHODDEF +#define OS_WIFSIGNALED_METHODDEF +#endif /* OS_WIFSIGNALED_METHODDEF */ + +#ifndef OS_WIFEXITED_METHODDEF +#define OS_WIFEXITED_METHODDEF +#endif /* OS_WIFEXITED_METHODDEF */ + +#ifndef OS_WEXITSTATUS_METHODDEF +#define OS_WEXITSTATUS_METHODDEF +#endif /* OS_WEXITSTATUS_METHODDEF */ + +#ifndef OS_WTERMSIG_METHODDEF +#define OS_WTERMSIG_METHODDEF +#endif /* OS_WTERMSIG_METHODDEF */ + +#ifndef OS_WSTOPSIG_METHODDEF +#define OS_WSTOPSIG_METHODDEF +#endif /* OS_WSTOPSIG_METHODDEF */ + + +#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) +#ifdef _SCO_DS +/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the + needed definitions in sys/statvfs.h */ +#define _SVID3 +#endif +#include + +static PyObject* +_pystatvfs_fromstructstatvfs(struct statvfs st) { + PyObject *v = PyStructSequence_New(&StatVFSResultType); + if (v == NULL) + return NULL; + +#if !defined(HAVE_LARGEFILE_SUPPORT) + PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); + PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); + PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks)); + PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree)); + PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail)); + PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files)); + PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree)); + PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail)); + PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); + PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); +#else + PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); + PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); + PyStructSequence_SET_ITEM(v, 2, + PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks)); + PyStructSequence_SET_ITEM(v, 3, + PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree)); + PyStructSequence_SET_ITEM(v, 4, + PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail)); + PyStructSequence_SET_ITEM(v, 5, + PyLong_FromLongLong((PY_LONG_LONG) st.f_files)); + PyStructSequence_SET_ITEM(v, 6, + PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree)); + PyStructSequence_SET_ITEM(v, 7, + PyLong_FromLongLong((PY_LONG_LONG) st.f_favail)); + PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); + PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); +#endif + if (PyErr_Occurred()) { + Py_DECREF(v); + return NULL; + } + + return v; +} + + +/*[clinic input] +os.fstatvfs + fd: int + / + +Perform an fstatvfs system call on the given fd. + +Equivalent to statvfs(fd). +[clinic start generated code]*/ + +PyDoc_STRVAR(os_fstatvfs__doc__, +"fstatvfs($module, fd, /)\n" +"--\n" +"\n" +"Perform an fstatvfs system call on the given fd.\n" +"\n" +"Equivalent to statvfs(fd)."); + +#define OS_FSTATVFS_METHODDEF \ + {"fstatvfs", (PyCFunction)os_fstatvfs, METH_VARARGS, os_fstatvfs__doc__}, + +static PyObject * +os_fstatvfs_impl(PyModuleDef *module, int fd); + +static PyObject * +os_fstatvfs(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + + if (!PyArg_ParseTuple(args, + "i:fstatvfs", + &fd)) + goto exit; + return_value = os_fstatvfs_impl(module, fd); + +exit: + return return_value; +} + +static PyObject * +os_fstatvfs_impl(PyModuleDef *module, int fd) +/*[clinic end generated code: output=0e32bf07f946ec0d input=d8122243ac50975e]*/ +{ + int result; + int async_err = 0; + struct statvfs st; + + do { + Py_BEGIN_ALLOW_THREADS + result = fstatvfs(fd, &st); + Py_END_ALLOW_THREADS + } while (result != 0 && errno == EINTR && + !(async_err = PyErr_CheckSignals())); + if (result != 0) + return (!async_err) ? posix_error() : NULL; + + return _pystatvfs_fromstructstatvfs(st); +} +#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */ + + +#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) +#include +/*[clinic input] +os.statvfs + + path: path_t(allow_fd='PATH_HAVE_FSTATVFS') + +Perform a statvfs system call on the given path. + +path may always be specified as a string. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_statvfs__doc__, +"statvfs($module, /, path)\n" +"--\n" +"\n" +"Perform a statvfs system call on the given path.\n" +"\n" +"path may always be specified as a string.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_STATVFS_METHODDEF \ + {"statvfs", (PyCFunction)os_statvfs, METH_VARARGS|METH_KEYWORDS, os_statvfs__doc__}, + +static PyObject * +os_statvfs_impl(PyModuleDef *module, path_t *path); + +static PyObject * +os_statvfs(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", NULL}; + path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS); + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&:statvfs", _keywords, + path_converter, &path)) + goto exit; + return_value = os_statvfs_impl(module, &path); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +static PyObject * +os_statvfs_impl(PyModuleDef *module, path_t *path) +/*[clinic end generated code: output=00ff54983360b446 input=3f5c35791c669bd9]*/ +{ + int result; + struct statvfs st; + + Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_FSTATVFS + if (path->fd != -1) { +#ifdef __APPLE__ + /* handle weak-linking on Mac OS X 10.3 */ + if (fstatvfs == NULL) { + fd_specified("statvfs", path->fd); + return NULL; + } +#endif + result = fstatvfs(path->fd, &st); + } + else +#endif + result = statvfs(path->narrow, &st); + Py_END_ALLOW_THREADS + + if (result) { + return path_error(path); + } + + return _pystatvfs_fromstructstatvfs(st); +} +#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */ + + +#ifdef MS_WINDOWS +/*[clinic input] +os._getdiskusage + + path: Py_UNICODE + +Return disk usage statistics about the given path as a (total, free) tuple. +[clinic start generated code]*/ + +PyDoc_STRVAR(os__getdiskusage__doc__, +"_getdiskusage($module, /, path)\n" +"--\n" +"\n" +"Return disk usage statistics about the given path as a (total, free) tuple."); + +#define OS__GETDISKUSAGE_METHODDEF \ + {"_getdiskusage", (PyCFunction)os__getdiskusage, METH_VARARGS|METH_KEYWORDS, os__getdiskusage__doc__}, + +static PyObject * +os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path); + +static PyObject * +os__getdiskusage(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", NULL}; + Py_UNICODE *path; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "u:_getdiskusage", _keywords, + &path)) + goto exit; + return_value = os__getdiskusage_impl(module, path); + +exit: + return return_value; +} + +static PyObject * +os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path) +/*[clinic end generated code: output=054c972179b13708 input=6458133aed893c78]*/ +{ + BOOL retval; + ULARGE_INTEGER _, total, free; + + Py_BEGIN_ALLOW_THREADS + retval = GetDiskFreeSpaceExW(path, &_, &total, &free); + Py_END_ALLOW_THREADS + if (retval == 0) + return PyErr_SetFromWindowsErr(0); + + return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); +} +#endif /* MS_WINDOWS */ + + +/* This is used for fpathconf(), pathconf(), confstr() and sysconf(). + * It maps strings representing configuration variable names to + * integer values, allowing those functions to be called with the + * magic names instead of polluting the module's namespace with tons of + * rarely-used constants. There are three separate tables that use + * these definitions. + * + * This code is always included, even if none of the interfaces that + * need it are included. The #if hackery needed to avoid it would be + * sufficiently pervasive that it's not worth the loss of readability. + */ +struct constdef { + char *name; + long value; +}; + +static int +conv_confname(PyObject *arg, int *valuep, struct constdef *table, + size_t tablesize) +{ + if (PyLong_Check(arg)) { + *valuep = PyLong_AS_LONG(arg); + return 1; + } + else { + /* look up the value in the table using a binary search */ + size_t lo = 0; + size_t mid; + size_t hi = tablesize; + int cmp; + const char *confname; + if (!PyUnicode_Check(arg)) { + PyErr_SetString(PyExc_TypeError, + "configuration names must be strings or integers"); + return 0; + } + confname = _PyUnicode_AsString(arg); + if (confname == NULL) + return 0; + while (lo < hi) { + mid = (lo + hi) / 2; + cmp = strcmp(confname, table[mid].name); + if (cmp < 0) + hi = mid; + else if (cmp > 0) + lo = mid + 1; + else { + *valuep = table[mid].value; + return 1; + } + } + PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); + return 0; + } +} + + +#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) +static struct constdef posix_constants_pathconf[] = { +#ifdef _PC_ABI_AIO_XFER_MAX + {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, +#endif +#ifdef _PC_ABI_ASYNC_IO + {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, +#endif +#ifdef _PC_ASYNC_IO + {"PC_ASYNC_IO", _PC_ASYNC_IO}, +#endif +#ifdef _PC_CHOWN_RESTRICTED + {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, +#endif +#ifdef _PC_FILESIZEBITS + {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, +#endif +#ifdef _PC_LAST + {"PC_LAST", _PC_LAST}, +#endif +#ifdef _PC_LINK_MAX + {"PC_LINK_MAX", _PC_LINK_MAX}, +#endif +#ifdef _PC_MAX_CANON + {"PC_MAX_CANON", _PC_MAX_CANON}, +#endif +#ifdef _PC_MAX_INPUT + {"PC_MAX_INPUT", _PC_MAX_INPUT}, +#endif +#ifdef _PC_NAME_MAX + {"PC_NAME_MAX", _PC_NAME_MAX}, +#endif +#ifdef _PC_NO_TRUNC + {"PC_NO_TRUNC", _PC_NO_TRUNC}, +#endif +#ifdef _PC_PATH_MAX + {"PC_PATH_MAX", _PC_PATH_MAX}, +#endif +#ifdef _PC_PIPE_BUF + {"PC_PIPE_BUF", _PC_PIPE_BUF}, +#endif +#ifdef _PC_PRIO_IO + {"PC_PRIO_IO", _PC_PRIO_IO}, +#endif +#ifdef _PC_SOCK_MAXBUF + {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, +#endif +#ifdef _PC_SYNC_IO + {"PC_SYNC_IO", _PC_SYNC_IO}, +#endif +#ifdef _PC_VDISABLE + {"PC_VDISABLE", _PC_VDISABLE}, +#endif +#ifdef _PC_ACL_ENABLED + {"PC_ACL_ENABLED", _PC_ACL_ENABLED}, +#endif +#ifdef _PC_MIN_HOLE_SIZE + {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE}, +#endif +#ifdef _PC_ALLOC_SIZE_MIN + {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN}, +#endif +#ifdef _PC_REC_INCR_XFER_SIZE + {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE}, +#endif +#ifdef _PC_REC_MAX_XFER_SIZE + {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE}, +#endif +#ifdef _PC_REC_MIN_XFER_SIZE + {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE}, +#endif +#ifdef _PC_REC_XFER_ALIGN + {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN}, +#endif +#ifdef _PC_SYMLINK_MAX + {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX}, +#endif +#ifdef _PC_XATTR_ENABLED + {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED}, +#endif +#ifdef _PC_XATTR_EXISTS + {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, +#endif +#ifdef _PC_TIMESTAMP_RESOLUTION + {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, +#endif +}; + +static int +conv_path_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_pathconf, + sizeof(posix_constants_pathconf) + / sizeof(struct constdef)); +} +#endif + + +#ifdef HAVE_FPATHCONF +/*[clinic input] +os.fpathconf -> long + + fd: int + name: path_confname + / + +Return the configuration limit name for the file descriptor fd. + +If there is no limit, return -1. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_fpathconf__doc__, +"fpathconf($module, fd, name, /)\n" +"--\n" +"\n" +"Return the configuration limit name for the file descriptor fd.\n" +"\n" +"If there is no limit, return -1."); + +#define OS_FPATHCONF_METHODDEF \ + {"fpathconf", (PyCFunction)os_fpathconf, METH_VARARGS, os_fpathconf__doc__}, + +static long +os_fpathconf_impl(PyModuleDef *module, int fd, int name); + +static PyObject * +os_fpathconf(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int fd; + int name; + long _return_value; + + if (!PyArg_ParseTuple(args, + "iO&:fpathconf", + &fd, conv_path_confname, &name)) + goto exit; + _return_value = os_fpathconf_impl(module, fd, name); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +static long +os_fpathconf_impl(PyModuleDef *module, int fd, int name) +/*[clinic end generated code: output=3bf04b40e0523a8c input=5942a024d3777810]*/ +{ + long limit; + + errno = 0; + limit = fpathconf(fd, name); + if (limit == -1 && errno != 0) + posix_error(); + + return limit; +} +#endif /* HAVE_FPATHCONF */ + + +#ifdef HAVE_PATHCONF +/*[clinic input] +os.pathconf -> long + path: path_t(allow_fd='PATH_HAVE_FPATHCONF') + name: path_confname + +Return the configuration limit name for the file or directory path. + +If there is no limit, return -1. +On some platforms, path may also be specified as an open file descriptor. + If this functionality is unavailable, using it raises an exception. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_pathconf__doc__, +"pathconf($module, /, path, name)\n" +"--\n" +"\n" +"Return the configuration limit name for the file or directory path.\n" +"\n" +"If there is no limit, return -1.\n" +"On some platforms, path may also be specified as an open file descriptor.\n" +" If this functionality is unavailable, using it raises an exception."); + +#define OS_PATHCONF_METHODDEF \ + {"pathconf", (PyCFunction)os_pathconf, METH_VARARGS|METH_KEYWORDS, os_pathconf__doc__}, + +static long +os_pathconf_impl(PyModuleDef *module, path_t *path, int name); + +static PyObject * +os_pathconf(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "name", NULL}; + path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, PATH_HAVE_FPATHCONF); + int name; + long _return_value; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&O&:pathconf", _keywords, + path_converter, &path, conv_path_confname, &name)) + goto exit; + _return_value = os_pathconf_impl(module, &path, name); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong(_return_value); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +static long +os_pathconf_impl(PyModuleDef *module, path_t *path, int name) +/*[clinic end generated code: output=1a53e125b6cf63e4 input=bc3e2a985af27e5e]*/ +{ + long limit; + + errno = 0; +#ifdef HAVE_FPATHCONF + if (path->fd != -1) + limit = fpathconf(path->fd, name); + else +#endif + limit = pathconf(path->narrow, name); + if (limit == -1 && errno != 0) { + if (errno == EINVAL) + /* could be a path or name problem */ + posix_error(); + else + path_error(path); + } + + return limit; +} +#endif /* HAVE_PATHCONF */ + +#ifdef HAVE_CONFSTR +static struct constdef posix_constants_confstr[] = { +#ifdef _CS_ARCHITECTURE + {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, +#endif +#ifdef _CS_GNU_LIBC_VERSION + {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION}, +#endif +#ifdef _CS_GNU_LIBPTHREAD_VERSION + {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION}, +#endif +#ifdef _CS_HOSTNAME + {"CS_HOSTNAME", _CS_HOSTNAME}, +#endif +#ifdef _CS_HW_PROVIDER + {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, +#endif +#ifdef _CS_HW_SERIAL + {"CS_HW_SERIAL", _CS_HW_SERIAL}, +#endif +#ifdef _CS_INITTAB_NAME + {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, +#endif +#ifdef _CS_LFS64_CFLAGS + {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, +#endif +#ifdef _CS_LFS64_LDFLAGS + {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, +#endif +#ifdef _CS_LFS64_LIBS + {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, +#endif +#ifdef _CS_LFS64_LINTFLAGS + {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, +#endif +#ifdef _CS_LFS_CFLAGS + {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, +#endif +#ifdef _CS_LFS_LDFLAGS + {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, +#endif +#ifdef _CS_LFS_LIBS + {"CS_LFS_LIBS", _CS_LFS_LIBS}, +#endif +#ifdef _CS_LFS_LINTFLAGS + {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, +#endif +#ifdef _CS_MACHINE + {"CS_MACHINE", _CS_MACHINE}, +#endif +#ifdef _CS_PATH + {"CS_PATH", _CS_PATH}, +#endif +#ifdef _CS_RELEASE + {"CS_RELEASE", _CS_RELEASE}, +#endif +#ifdef _CS_SRPC_DOMAIN + {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, +#endif +#ifdef _CS_SYSNAME + {"CS_SYSNAME", _CS_SYSNAME}, +#endif +#ifdef _CS_VERSION + {"CS_VERSION", _CS_VERSION}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS + {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS + {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LIBS + {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS + {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS + {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS + {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS + {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS + {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_CFLAGS + {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS + {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LIBS + {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS + {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS + {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS + {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS + {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS + {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, +#endif +#ifdef _MIPS_CS_AVAIL_PROCESSORS + {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, +#endif +#ifdef _MIPS_CS_BASE + {"MIPS_CS_BASE", _MIPS_CS_BASE}, +#endif +#ifdef _MIPS_CS_HOSTID + {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, +#endif +#ifdef _MIPS_CS_HW_NAME + {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, +#endif +#ifdef _MIPS_CS_NUM_PROCESSORS + {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, +#endif +#ifdef _MIPS_CS_OSREL_MAJ + {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, +#endif +#ifdef _MIPS_CS_OSREL_MIN + {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, +#endif +#ifdef _MIPS_CS_OSREL_PATCH + {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, +#endif +#ifdef _MIPS_CS_OS_NAME + {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, +#endif +#ifdef _MIPS_CS_OS_PROVIDER + {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, +#endif +#ifdef _MIPS_CS_PROCESSORS + {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, +#endif +#ifdef _MIPS_CS_SERIAL + {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, +#endif +#ifdef _MIPS_CS_VENDOR + {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, +#endif +}; + +static int +conv_confstr_confname(PyObject *arg, int *valuep) +{ + return conv_confname(arg, valuep, posix_constants_confstr, + sizeof(posix_constants_confstr) + / sizeof(struct constdef)); +} + + +/*[clinic input] +os.confstr + + name: confstr_confname + / + +Return a string-valued system configuration variable. +[clinic start generated code]*/ + +PyDoc_STRVAR(os_confstr__doc__, +"confstr($module, name, /)\n" +"--\n" +"\n" +"Return a string-valued system configuration variable."); + +#define OS_CONFSTR_METHODDEF \ + {"confstr", (PyCFunction)os_confstr, METH_VARARGS, os_confstr__doc__}, + +static PyObject * +os_confstr_impl(PyModuleDef *module, int name); + +static PyObject * +os_confstr(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int name; + + if (!PyArg_ParseTuple(args, + "O&:confstr", + conv_confstr_confname, &name)) + goto exit; + return_value = os_confstr_impl(module, name); + +exit: + return return_value; +} + +static PyObject * +os_confstr_impl(PyModuleDef *module, int name) +/*[clinic end generated code: output=3f5e8aba9f8e3174 input=18fb4d0567242e65]*/ +{ + PyObject *result = NULL; + char buffer[255]; + size_t len; + + errno = 0; + len = confstr(name, buffer, sizeof(buffer)); + if (len == 0) { + if (errno) { + posix_error(); + return NULL; + } + else { + Py_RETURN_NONE; + } + } + + if (len >= sizeof(buffer)) { + size_t len2; + char *buf = PyMem_Malloc(len); + if (buf == NULL) + return PyErr_NoMemory(); + len2 = confstr(name, buf, len); + assert(len == len2); + result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1); + PyMem_Free(buf); + } + else + result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); + return result; +} +#endif /* HAVE_CONFSTR */ + + +#ifdef HAVE_SYSCONF +static struct constdef posix_constants_sysconf[] = { +#ifdef _SC_2_CHAR_TERM + {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, +#endif +#ifdef _SC_2_C_BIND + {"SC_2_C_BIND", _SC_2_C_BIND}, +#endif +#ifdef _SC_2_C_DEV + {"SC_2_C_DEV", _SC_2_C_DEV}, +#endif +#ifdef _SC_2_C_VERSION + {"SC_2_C_VERSION", _SC_2_C_VERSION}, +#endif +#ifdef _SC_2_FORT_DEV + {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, +#endif +#ifdef _SC_2_FORT_RUN + {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, +#endif +#ifdef _SC_2_LOCALEDEF + {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, +#endif +#ifdef _SC_2_SW_DEV + {"SC_2_SW_DEV", _SC_2_SW_DEV}, +#endif +#ifdef _SC_2_UPE + {"SC_2_UPE", _SC_2_UPE}, +#endif +#ifdef _SC_2_VERSION + {"SC_2_VERSION", _SC_2_VERSION}, +#endif +#ifdef _SC_ABI_ASYNCHRONOUS_IO + {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, +#endif +#ifdef _SC_ACL + {"SC_ACL", _SC_ACL}, +#endif +#ifdef _SC_AIO_LISTIO_MAX + {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, +#endif +#ifdef _SC_AIO_MAX + {"SC_AIO_MAX", _SC_AIO_MAX}, +#endif +#ifdef _SC_AIO_PRIO_DELTA_MAX + {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, +#endif +#ifdef _SC_ARG_MAX + {"SC_ARG_MAX", _SC_ARG_MAX}, +#endif +#ifdef _SC_ASYNCHRONOUS_IO + {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, +#endif +#ifdef _SC_ATEXIT_MAX + {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, +#endif +#ifdef _SC_AUDIT + {"SC_AUDIT", _SC_AUDIT}, +#endif +#ifdef _SC_AVPHYS_PAGES + {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, +#endif +#ifdef _SC_BC_BASE_MAX + {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, +#endif +#ifdef _SC_BC_DIM_MAX + {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, +#endif +#ifdef _SC_BC_SCALE_MAX + {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, +#endif +#ifdef _SC_BC_STRING_MAX + {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, +#endif +#ifdef _SC_CAP + {"SC_CAP", _SC_CAP}, +#endif +#ifdef _SC_CHARCLASS_NAME_MAX + {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, +#endif +#ifdef _SC_CHAR_BIT + {"SC_CHAR_BIT", _SC_CHAR_BIT}, +#endif +#ifdef _SC_CHAR_MAX + {"SC_CHAR_MAX", _SC_CHAR_MAX}, +#endif +#ifdef _SC_CHAR_MIN + {"SC_CHAR_MIN", _SC_CHAR_MIN}, +#endif +#ifdef _SC_CHILD_MAX + {"SC_CHILD_MAX", _SC_CHILD_MAX}, +#endif +#ifdef _SC_CLK_TCK + {"SC_CLK_TCK", _SC_CLK_TCK}, +#endif +#ifdef _SC_COHER_BLKSZ + {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, +#endif +#ifdef _SC_COLL_WEIGHTS_MAX + {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, +#endif +#ifdef _SC_DCACHE_ASSOC + {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, +#endif +#ifdef _SC_DCACHE_BLKSZ + {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, +#endif +#ifdef _SC_DCACHE_LINESZ + {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, +#endif +#ifdef _SC_DCACHE_SZ + {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, +#endif +#ifdef _SC_DCACHE_TBLKSZ + {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, +#endif +#ifdef _SC_DELAYTIMER_MAX + {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, +#endif +#ifdef _SC_EQUIV_CLASS_MAX + {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, +#endif +#ifdef _SC_EXPR_NEST_MAX + {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, +#endif +#ifdef _SC_FSYNC + {"SC_FSYNC", _SC_FSYNC}, +#endif +#ifdef _SC_GETGR_R_SIZE_MAX + {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, +#endif +#ifdef _SC_GETPW_R_SIZE_MAX + {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, +#endif +#ifdef _SC_ICACHE_ASSOC + {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, +#endif +#ifdef _SC_ICACHE_BLKSZ + {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, +#endif +#ifdef _SC_ICACHE_LINESZ + {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, +#endif +#ifdef _SC_ICACHE_SZ + {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, +#endif +#ifdef _SC_INF + {"SC_INF", _SC_INF}, +#endif +#ifdef _SC_INT_MAX + {"SC_INT_MAX", _SC_INT_MAX}, +#endif +#ifdef _SC_INT_MIN + {"SC_INT_MIN", _SC_INT_MIN}, +#endif +#ifdef _SC_IOV_MAX + {"SC_IOV_MAX", _SC_IOV_MAX}, +#endif +#ifdef _SC_IP_SECOPTS + {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, +#endif +#ifdef _SC_JOB_CONTROL + {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, +#endif +#ifdef _SC_KERN_POINTERS + {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, +#endif +#ifdef _SC_KERN_SIM + {"SC_KERN_SIM", _SC_KERN_SIM}, +#endif +#ifdef _SC_LINE_MAX + {"SC_LINE_MAX", _SC_LINE_MAX}, +#endif +#ifdef _SC_LOGIN_NAME_MAX + {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, +#endif +#ifdef _SC_LOGNAME_MAX + {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, +#endif +#ifdef _SC_LONG_BIT + {"SC_LONG_BIT", _SC_LONG_BIT}, +#endif +#ifdef _SC_MAC + {"SC_MAC", _SC_MAC}, +#endif +#ifdef _SC_MAPPED_FILES + {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, +#endif +#ifdef _SC_MAXPID + {"SC_MAXPID", _SC_MAXPID}, +#endif +#ifdef _SC_MB_LEN_MAX + {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, +#endif +#ifdef _SC_MEMLOCK + {"SC_MEMLOCK", _SC_MEMLOCK}, +#endif +#ifdef _SC_MEMLOCK_RANGE + {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, +#endif +#ifdef _SC_MEMORY_PROTECTION + {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION}, +#endif +#ifdef _SC_MESSAGE_PASSING + {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING}, +#endif +#ifdef _SC_MMAP_FIXED_ALIGNMENT + {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, +#endif +#ifdef _SC_MQ_OPEN_MAX + {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX}, #endif #ifdef _SC_MQ_PRIO_MAX {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},